比较 C# 中的 DateTimeOffset
Comparing DateTimeOffset's in C#
我正在尝试比较两个 DateTimeOffset,但 DateTimeOffset.Compare() 函数未按预期运行。我创建了示例脚本来演示该问题。在此示例中,我希望比较 dateA 和 dateB 的结果为零(相同)。
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");
你的时间跨度不一样,如果你使用适当的格式说明符就可以看出这一点,例如往返格式 "o"
.
dateA.ToString("o")
这里有一些关于 how to truncate the milliseconds 的例子。
Sleep(1)
只会休眠 1 毫秒。所以大概 dateA
和 dateB
只相隔 1 或 2 毫秒。
由于您仅将 date/time 值打印到分钟和秒,因此您看不到实际差异。如果您使用 Console.WriteLine("dateA =" + dateA.ToString("dd/MM/yyyy HH:mm:ss.fff");
,您会看到不同之处。
如果你打算等待 1 秒,你应该做一个 Sleep(1000)
首先,DateTimeOffset
和DateTime
比毫秒更精确。它们所代表的最小单位是"tick",即100ns。也就是说,小数秒有七位小数,而不是三位。 (计算机的时钟本身并没有那么精确,但是这些数据结构仍然可以以这种精度表示值。)
最后,你问了(在问题评论中):
... how do I compare two datetimeoffset's ignoring the milliseconds?
所以知道我们知道你在问什么,请考虑仅忽略小数秒不会解决问题。
考虑如果 A
有 3.9999999 秒,而 B
有 4.0000001.
截断小数将得到 A == 3
、B == 4
,因此 A != B
.
考虑如果 A
有 3.4999999 秒,而 B
有 3.5000001.
四舍五入小数将得到 A == 3
、B == 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
的实现与此几乎相同,所以是的 - 这种方法很好。尽管您可能更喜欢我的实现以提高可读性和更好地控制阈值,但您是否应该决定将其更改为其他内容。
我正在尝试比较两个 DateTimeOffset,但 DateTimeOffset.Compare() 函数未按预期运行。我创建了示例脚本来演示该问题。在此示例中,我希望比较 dateA 和 dateB 的结果为零(相同)。
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");
你的时间跨度不一样,如果你使用适当的格式说明符就可以看出这一点,例如往返格式 "o"
.
dateA.ToString("o")
这里有一些关于 how to truncate the milliseconds 的例子。
Sleep(1)
只会休眠 1 毫秒。所以大概 dateA
和 dateB
只相隔 1 或 2 毫秒。
由于您仅将 date/time 值打印到分钟和秒,因此您看不到实际差异。如果您使用 Console.WriteLine("dateA =" + dateA.ToString("dd/MM/yyyy HH:mm:ss.fff");
,您会看到不同之处。
如果你打算等待 1 秒,你应该做一个 Sleep(1000)
首先,DateTimeOffset
和DateTime
比毫秒更精确。它们所代表的最小单位是"tick",即100ns。也就是说,小数秒有七位小数,而不是三位。 (计算机的时钟本身并没有那么精确,但是这些数据结构仍然可以以这种精度表示值。)
最后,你问了(在问题评论中):
... how do I compare two datetimeoffset's ignoring the milliseconds?
所以知道我们知道你在问什么,请考虑仅忽略小数秒不会解决问题。
考虑如果
A
有 3.9999999 秒,而B
有 4.0000001.
截断小数将得到A == 3
、B == 4
,因此A != B
.考虑如果
A
有 3.4999999 秒,而B
有 3.5000001.
四舍五入小数将得到A == 3
、B == 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
的实现与此几乎相同,所以是的 - 这种方法很好。尽管您可能更喜欢我的实现以提高可读性和更好地控制阈值,但您是否应该决定将其更改为其他内容。