简体   繁体   中英

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");

Your Timespans are not the same, as can be seen if you use an appropriate format specifier, eg round trip format "o" .

dateA.ToString("o")

Here are some examples on how to truncate the milliseconds .

Sleep(1) will only sleep for 1 millisecond. So presumably dateA and dateB are only 1 or 2 milliseconds apart.

Since you are printing the date/time value only to minutes and seconds, you do not see the actual difference. If you were to use the Console.WriteLine("dateA =" + dateA.ToString("dd/MM/yyyy HH:mm:ss.fff"); you'd see the difference.

If you meant to wait for 1 second, you should do a Sleep(1000)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM