开发者

C# DateTime comparisons accuracy and rounding

I have two dates. One supplied by the user and accurate to the second and one from the database and accurate to the tick level. This means when they both represent 13/11/2009 17:22:17 (British dates)

userTime开发者_JAVA技巧 == dbTime 

returns false

The tick values are 633937297368344183 and 633937297370000000.

To fix this I use the code

userTime = new DateTime(
                userTime.Year, 
                userTime.Month, 
                userTime.Day, 
                userTime.Hour, 
                userTime.Minute, 
                userTime.Second);

dbTime = new DateTime(
                dbTime.Year, 
                dbTime.Month, 
                dbTime.Day, 
                dbTime.Hour, 
                dbTime.Minute, 
                dbTime.Second);

Is there a more elegant way to achieve this?


The most obvious refactoring would be to remove the duplication:

public static DateTime TruncateToSecond(DateTime original)
{
    return new DateTime(original.Year, original.Month, original.Day,
        original.Hour, original.Minute, original.Second);
}

...
if (TruncateToSecond(userTime) == TruncateToSecond(dbTime))
    ...

You could quite possibly write:

if (userTime.Ticks / TimeSpan.TicksPerSecond
    == dbTime.Ticks / TimeSpan.TicksPerSecond)
   ...

I believe that would work, simply because tick 0 is at the start of a second.

You ought to be careful about the time zone aspect of all of this, of course. You might want to consider using DateTimeOffset instead.


Can you try

UserDateTime.Substract(dbDateTime).TotalSeconds == 0


I subtract them, and get a TimeSpan object. Then take the value of that difference (or the absolute value of the difference, whichever is appropriate for you), and compare that to a small threshold value, like 0.002s.

TimeSpan delta = dt1 - dt2;

// get the delta as an absolute value:
if (delta < new TimeSpan(0, 0, 0))
    delta = new TimeSpan(0, 0, 0) - delta;

// My threshold is 1 second.  The difference can be no more than 1 second. 
TimeSpan threshold = new TimeSpan(0, 0, 1);

if (delta > threshold)
{
    // error...
}


Very similar to Cheeso I've written this extension for DateTime that is especially used in unit tests:

public static bool IsSimilarTo(this DateTime thisDateTime, DateTime otherDateTime, TimeSpan tolerance)
{
    DateTime allowedMinimum = thisDateTime.Subtract(tolerance);
    DateTime allowedMaximum = thisDateTime.Add(tolerance);

    if (otherDateTime < allowedMinimum || otherDateTime > allowedMaximum)
    {
        return false;
    }

    return true;
}

It will help you with your issue, should be in a basic library :-)


you could use Microsoft.VisualBasic namespace and then

  DateTime a = new DateTime(633937297368344183L);
  DateTime b = new DateTime(633937297370000000L);

  Console.WriteLine(Microsoft.VisualBasic.DateAndTime.DateDiff(DateInterval.Second, a, b,FirstDayOfWeek.Sunday ,FirstWeekOfYear.System) == 0); //true

It seem under C# you need to specify the FirstDayOfWeek and FirstWeekOfYear.

Not under VB.net

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜