diff options
author | Warren Falk <warren@warrenfalk.com> | 2018-07-09 17:26:36 -0400 |
---|---|---|
committer | Jie Luo <anandolee@gmail.com> | 2018-07-09 14:26:36 -0700 |
commit | 96833b8f4b1897ae2a4ddf21ec9d1c5e6eabc8c7 (patch) | |
tree | d654dcd7cd94896f732b8c71c61d36c1d2ebb959 | |
parent | 5524c53e602828430da9e7b405135c0961e868da (diff) |
implement IComparable and comparison operators on Timestamp (#4318)
-rw-r--r-- | csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs | 101 | ||||
-rw-r--r-- | csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs | 105 |
2 files changed, 205 insertions, 1 deletions
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs index 9ecd24c6..b8c07ef5 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs @@ -111,5 +111,106 @@ namespace Google.Protobuf.WellKnownTypes var duration = new Timestamp { Seconds = 1, Nanos = -1 }; Assert.AreEqual("{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString()); } + + [Test] + public void Comparability() + { + Timestamp + a = null, + b = new Timestamp { Seconds = 1, Nanos = 1 }, + c = new Timestamp { Seconds = 1, Nanos = 10 }, + d = new Timestamp { Seconds = 10, Nanos = 1 }, + e = new Timestamp { Seconds = 10, Nanos = 10 }; + + Assert.IsTrue(b.CompareTo(a) > 0); // null is always first (according to default behavior of Array.Sort) + Assert.IsTrue(b.CompareTo(b) == 0); + Assert.IsTrue(b.CompareTo(b.Clone()) == 0); + Assert.IsTrue(b.CompareTo(c) < 0); + Assert.IsTrue(b.CompareTo(d) < 0); + Assert.IsTrue(b.CompareTo(e) < 0); + + Assert.IsTrue(c.CompareTo(a) > 0); + Assert.IsTrue(c.CompareTo(b) > 0); + Assert.IsTrue(c.CompareTo(c) == 0); + Assert.IsTrue(c.CompareTo(c.Clone()) == 0); + Assert.IsTrue(c.CompareTo(d) < 0); + Assert.IsTrue(c.CompareTo(e) < 0); + + Assert.IsTrue(d.CompareTo(a) > 0); + Assert.IsTrue(d.CompareTo(b) > 0); + Assert.IsTrue(d.CompareTo(c) > 0); + Assert.IsTrue(d.CompareTo(d) == 0); + Assert.IsTrue(d.CompareTo(d.Clone()) == 0); + Assert.IsTrue(d.CompareTo(e) < 0); + + Assert.IsTrue(e.CompareTo(a) > 0); + Assert.IsTrue(e.CompareTo(b) > 0); + Assert.IsTrue(e.CompareTo(c) > 0); + Assert.IsTrue(e.CompareTo(d) > 0); + Assert.IsTrue(e.CompareTo(e) == 0); + Assert.IsTrue(e.CompareTo(e.Clone()) == 0); + } + + + [Test] + public void ComparabilityOperators() + { + Timestamp + a = null, + b = new Timestamp { Seconds = 1, Nanos = 1 }, + c = new Timestamp { Seconds = 1, Nanos = 10 }, + d = new Timestamp { Seconds = 10, Nanos = 1 }, + e = new Timestamp { Seconds = 10, Nanos = 10 }; + +#pragma warning disable CS1718 // Comparison made to same variable + Assert.IsTrue(b > a); + Assert.IsTrue(b == b); + Assert.IsTrue(b == b.Clone()); + Assert.IsTrue(b < c); + Assert.IsTrue(b < d); + Assert.IsTrue(b < e); + + Assert.IsTrue(c > a); + Assert.IsTrue(c > b); + Assert.IsTrue(c == c); + Assert.IsTrue(c == c.Clone()); + Assert.IsTrue(c < d); + Assert.IsTrue(c < e); + + Assert.IsTrue(d > a); + Assert.IsTrue(d > b); + Assert.IsTrue(d > c); + Assert.IsTrue(d == d); + Assert.IsTrue(d == d.Clone()); + Assert.IsTrue(d < e); + + Assert.IsTrue(e > a); + Assert.IsTrue(e > b); + Assert.IsTrue(e > c); + Assert.IsTrue(e > d); + Assert.IsTrue(e == e); + Assert.IsTrue(e == e.Clone()); + + Assert.IsTrue(b >= a); + Assert.IsTrue(b <= c); + Assert.IsTrue(b <= d); + Assert.IsTrue(b <= e); + + Assert.IsTrue(c >= a); + Assert.IsTrue(c >= b); + Assert.IsTrue(c <= d); + Assert.IsTrue(c <= e); + + Assert.IsTrue(d >= a); + Assert.IsTrue(d >= b); + Assert.IsTrue(d >= c); + Assert.IsTrue(d <= e); + + Assert.IsTrue(e >= a); + Assert.IsTrue(e >= b); + Assert.IsTrue(e >= c); + Assert.IsTrue(e >= d); +#pragma warning restore CS1718 // Comparison made to same variable + } } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs index aa403473..a9251974 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs @@ -36,7 +36,7 @@ using System.Text; namespace Google.Protobuf.WellKnownTypes { - public partial class Timestamp : ICustomDiagnosticMessage + public partial class Timestamp : ICustomDiagnosticMessage, IComparable<Timestamp> { private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // Constants determined programmatically, but then hard-coded so they can be constant expressions. @@ -223,6 +223,109 @@ namespace Google.Protobuf.WellKnownTypes } /// <summary> + /// Given another timestamp, returns 0 if the timestamps are equivalent, -1 if this timestamp precedes the other, and 1 otherwise + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="other">Timestamp to compare</param> + /// <returns>an integer indicating whether this timestamp precedes or follows the other</returns> + public int CompareTo(Timestamp other) + { + return other == null ? 1 + : Seconds < other.Seconds ? -1 + : Seconds > other.Seconds ? 1 + : Nanos < other.Nanos ? -1 + : Nanos > other.Nanos ? 1 + : 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a precedes b</returns> + public static bool operator <(Timestamp a, Timestamp b) + { + return a.CompareTo(b) < 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a follows b</returns> + public static bool operator >(Timestamp a, Timestamp b) + { + return a.CompareTo(b) > 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a precedes b</returns> + public static bool operator <=(Timestamp a, Timestamp b) + { + return a.CompareTo(b) <= 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a follows b</returns> + public static bool operator >=(Timestamp a, Timestamp b) + { + return a.CompareTo(b) >= 0; + } + + + /// <summary> + /// Returns whether two timestamps are equivalent + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if the two timestamps refer to the same nanosecond</returns> + public static bool operator ==(Timestamp a, Timestamp b) + { + return ReferenceEquals(a, b) || (a is null ? (b is null ? true : false) : a.Equals(b)); + } + + /// <summary> + /// Returns whether two timestamps differ + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if the two timestamps differ</returns> + public static bool operator !=(Timestamp a, Timestamp b) + { + return !(a == b); + } + + /// <summary> /// Returns a string representation of this <see cref="Timestamp"/> for diagnostic purposes. /// </summary> /// <remarks> |