implement IComparable and comparison operators on Timestamp (#4318)

pull/3959/merge
Warren Falk 6 years ago committed by Jie Luo
parent 5524c53e60
commit 96833b8f4b
  1. 101
      csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
  2. 105
      csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.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
}
}
}

@ -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.
@ -222,6 +222,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>

Loading…
Cancel
Save