Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing DateTimeOffset's in C#

I'm trying to compare two DateTimeOffsets but the DateTimeOffset.Compare() function is not functioning as expected. I have created the example script to demonstrate the issue. In this example I expected the result of comparing dateA and dateB to be zero (The same).

using System;
namespace ComparingDateTimeOffset
{
   class Program
   {
       static void Main(string[] args)
       {
           DateTimeOffset dateA = DateTimeOffset.Now;
           Thread.Sleep(1);
           DateTimeOffset dateB = DateTimeOffset.Now;

           Console.WriteLine("dateA =" + dateA);
           Console.WriteLine("dateB =" + dateB);

           Console.WriteLine(DateTimeOffset.Compare(dateA, dateB) == 0
            ? "dateA and dateB are the same"
            : "dateA and dateB are NOT the same");

           Console.WriteLine("Press any key to exit");
           Console.ReadKey();
       }
   }
}

The results of the above program are

dateA =17/02/2016 09:09:21 +00:00
dateB =17/02/2016 09:09:21 +00:00
dateA and dateB are NOT the same
Press any key to exit

In the console output it looks like the two dates are equal. But the compare function says the two dates are different. The following code shows that there are a few milliseconds difference between the two dates.

long diff = (long) (dateB - dateA).TotalMilliseconds;
Console.WriteLine("Time differance in milliseconds =" + diff);

To avoid using the DateTimeOffset.Compare function. I have decided to calculate the difference between the dates in seconds and then round to the nearest integer. This seams to work. Can anyone see a disadvantage of using this method?

Console.WriteLine((int)(dateB - dateA).TotalSeconds == 0
            ? "dateA and dateB are the same"
            : "dateA and dateB are NOT the same");
like image 507
Andrew Seaford Avatar asked Jan 18 '26 12:01

Andrew Seaford


1 Answers

First of all, DateTimeOffset and DateTime have finer precision than milliseconds. The smallest unit they represent is a "tick" which is 100ns. In other words, there are seven decimal places of fractional seconds, not three. (The computer's clock itself is not that precise, but these data structures can still represent values with this precision.)

Ultimately, you asked (in the question comments):

... how do I compare two datetimeoffset's ignoring the milliseconds?

So know we know what you're asking, consider that just ignoring fractional seconds will not solve the problem.

  • Consider if A had 3.9999999 seconds, and B had 4.0000001.
    Truncating decimals would give A == 3, B == 4, so A != B.

  • Consider if A had 3.4999999 seconds, and B had 3.5000001.
    Rounding decimals would give A == 3, B == 4, so A != B.

So neither truncation or rounding will solve all use cases. You cannot guarantee that the value between two consecutive clock readings will be truncated or rounded to the same value.

Instead, as you suggested, decide what the smallest difference between two values you will allow to consider them the same. For example, if you think anything under one second apart is inconsequential, then:

if ((dateB - dateA) < TimeSpan.FromSeconds(1))
{
    // equivalent, within 1s threshold
}
else
{
    // not equivalent or within threshold.
    // you could continue with normal comparison to determine < or > if desired
}

Your implementation of: (int)(dateB - dateA).TotalSeconds == 0 is pretty much the same thing as this, so yes - that approach is fine. Though you may prefer my implementation for readability, and for better control over the threshold value, should you decide to change it to something else.

like image 109
Matt Johnson-Pint Avatar answered Jan 21 '26 00:01

Matt Johnson-Pint



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!