aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorWarren Falk <warren@warrenfalk.com>2018-07-09 17:26:36 -0400
committerJie Luo <anandolee@gmail.com>2018-07-09 14:26:36 -0700
commit96833b8f4b1897ae2a4ddf21ec9d1c5e6eabc8c7 (patch)
treed654dcd7cd94896f732b8c71c61d36c1d2ebb959
parent5524c53e602828430da9e7b405135c0961e868da (diff)
implement IComparable and comparison operators on Timestamp (#4318)
-rw-r--r--csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs101
-rw-r--r--csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs105
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>