比较 C# 中的日期时间偏移量

本文关键字:时间 偏移量 日期 比较 | 更新日期: 2023-09-27 18:34:53

我正在尝试比较两个DateTimeOffsets,但DateTimeOffset.Compare((函数没有按预期运行。我创建了示例脚本来演示该问题。在此示例中,我期望比较日期 A 和日期 B 的结果为零(相同(。

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

上述计划的结果是

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

在控制台输出中,两个日期看起来相等。但是比较函数说两个日期是不同的。下面的代码显示两个日期之间存在几毫秒的差异。

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

避免使用 DateTimeOffset.Compare 函数。我决定以秒为单位计算日期之间的差异,然后四舍五入到最接近的整数。这个接缝工作。任何人都可以看到使用这种方法的缺点吗?

Console.WriteLine((int)(dateB - dateA).TotalSeconds == 0
            ? "dateA and dateB are the same"
            : "dateA and dateB are NOT the same");

比较 C# 中的日期时间偏移量

首先,DateTimeOffsetDateTime的精度比毫秒更精细。 它们表示的最小单位是 100ns 的"刻度"。 换句话说,小数秒的小数点有七个位,而不是三个。 (计算机的时钟本身并不那么精确,但这些数据结构仍然可以以这种精度表示

最终,您问(在问题评论中(:

。如何比较两个忽略毫秒的日期时间偏移量?

所以要知道我们知道你在问什么,考虑到仅仅忽略秒数并不能解决问题。

  • 考虑一下A是否有 3.9999999 秒,B有 4.0000001。
    截断小数会得到A == 3B == 4,所以A != B

  • 考虑一下A是否有 3.4999999 秒,B有 3.5000001。
    四舍五入的小数将得到A == 3B == 4,所以A != B

因此截断或舍入都无法解决所有用例。 您无法保证两个连续时钟读数之间的值将被截断或舍入为相同的值。

相反,正如您所建议的,确定两个值之间的最小差异,您将允许将它们视为相同。 例如,如果您认为相隔不到一秒的任何内容都无关紧要,那么:

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
}

您的实现:(int)(dateB - dateA).TotalSeconds == 0与此几乎相同,所以是的 - 这种方法很好。 尽管您可能更喜欢我的实现以提高可读性,并更好地控制阈值,但如果您决定将其更改为其他内容。

您的时间跨度不同,如果您使用适当的格式说明符(例如往返格式"o",则可以看出。

dateA.ToString("o")

下面是有关如何截断毫秒的一些示例。

Sleep(1)只会休眠 1 毫秒。所以大概dateAdateB只有1或2毫秒的距离。

由于仅将日期/时间值打印为分钟和秒,因此看不到实际差异。如果你使用Console.WriteLine("dateA =" + dateA.ToString("dd/MM/yyyy HH:mm:ss.fff");你会看到区别。

如果你打算等待1秒钟,你应该做一个Sleep(1000)