【问题标题】:C# DateTime comparisons accuracy and roundingC# DateTime 比较准确性和舍入
【发布时间】:2009-11-19 13:52:42
【问题描述】:

我有两个约会。一个由用户提供,精确到第二个,一个来自数据库,精确到刻度线。这意味着当它们都代表 13/11/2009 17:22:17(英国日期)时

userTime == dbTime 

返回假

刻度值为 633937297368344183 和 633937297370000000。

为了解决这个问题,我使用了代码

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

有没有更优雅的方法来实现这一点?

【问题讨论】:

    标签: c# datetime


    【解决方案1】:

    最明显的重构是删除重复:

    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))
        ...
    

    你很可能会写:

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

    相信这会起作用,仅仅是因为第 0 个刻度是在一秒的开始。

    当然,您应该注意所有这些的时区方面。您可能要考虑改用DateTimeOffset

    【讨论】:

      【解决方案2】:

      你可以试试

      UserDateTime.Substract(dbDateTime).TotalSeconds == 0
      

      【讨论】:

        【解决方案3】:

        我减去它们,得到一个 TimeSpan 对象。然后取该差异的值(或差异的绝对值,以适合您的为准),并将其与一个小的阈值进行比较,例如 0.002 秒。

        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...
        }
        

        【讨论】:

          【解决方案4】:

          与 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;
          }
          

          它将帮助您解决问题,应该在基本库中:-)

          【讨论】:

            【解决方案5】:

            你可以使用 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
            

            在 C# 下,您似乎需要指定 FirstDayOfWeekFirstWeekOfYear

            不在VB.net下

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-03-20
              • 1970-01-01
              • 1970-01-01
              • 2015-10-18
              • 1970-01-01
              • 2019-07-18
              • 2013-08-08
              • 1970-01-01
              相关资源
              最近更新 更多