简体   繁体   English

C#DateTime比较准确性和舍入

[英]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) 这意味着当他们都代表13/11/2009 17:22:17(英国约会)

userTime == dbTime 

returns false 返回false

The tick values are 633937297368344183 and 633937297370000000. 刻度值为633937297368344183和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. 相信这会奏效,因为刻度0是在一秒的开始。

You ought to be careful about the time zone aspect of all of this, of course. 当然,你应该小心所有这些的时区方面。 You might want to consider using DateTimeOffset instead. 您可能需要考虑使用DateTimeOffset

你能试一下吗

UserDateTime.Substract(dbDateTime).TotalSeconds == 0

I subtract them, and get a TimeSpan object. 我减去它们,得到一个TimeSpan对象。 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. 然后取该差值的值(或差值的绝对值,以适合您的为准),并将其与小阈值(如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: 与Cheeso非常相似我为DateTime编写了这个扩展,特别用于单元测试:

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 您可以使用Microsoft.VisualBasic命名空间

  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 . 看来在C#下你需要指定FirstDayOfWeekFirstWeekOfYear

Not under VB.net 不在VB.net下

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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