DateTime.AddDays的准确度如何?

时间:2009-04-20 16:14:34

标签: c# datetime rounding

由于DateTime.AddDays()采用double参数,我担心当你添加一天时,可能会出现一些舍入错误。例如,假设我有以下循环:

DateTime Now = DateTime.Today;
for (int i = 0; i < 365; ++i)
{
    Now = Now.AddDays(1);
    // do something
}

我担心现在可能会从午夜开始漂流。我总是想做一些像这样的事情,这可能会慢一些,但我的偏执有所缓解:

for (int i = 0; i < 365; ++i)
{
    Now = Now.AddDays(1.01).Date;
    // do something
}

5 个答案:

答案 0 :(得分:11)

由于DateTime将日期内部存储为64位整数,其中一个刻度表示100纳秒,因此不存在错误风险。一天有864,000,000,000个刻度,Double的精度至少为15位。因此,当舍入到滴答时,每个错误都会消失,因为如果Double等于一天,1.0的分辨率高于一个滴答。

对于AddYears(),情况并非如此,因为如果Double等于一年,1.0没有足够的精度来表示一个刻度线。但是如果你看一下DateTime类,你会发现设计尊重这个事实 - AddMonths()AddYears()都有整数和非浮点参数。

要检查这一点,只需执行以下代码。

DateTime now = DateTime.Now;

// Displays 864000000000 
Console.WriteLine(now.AddDays(1.0).Ticks - now.Ticks);

答案 1 :(得分:2)

一般情况下,我认为你担心使用双打进行舍入是正确的,因为不是所有的实数都可以用双精度表示 - 例如,如果你每天增加1/3的三次,你可能不会最后只有一天的进展。但是,在这种情况下,1是一个绝对可以表达的数字,并且你只是将它乘以另一个在双精度中绝对可表达的数字(一天中的刻度数),你应该没问题。第二个样本可能是矫枉过正。

示例:

DateTime now = DateTime.Today;
for (int i = 0; i < 7; ++i )
{
    for (int j = 0; j < 7; ++j )
    {
         now = now.AddDays( 1 / 7.0 );
    }
}
Console.WriteLine( DateTime.Today);
Console.WriteLine( now );

结果(2009年4月20日)

4/20/2009 12:00:00 AM
4/26/2009 11:59:59 PM

答案 2 :(得分:1)

天数乘以整数(比例),然后加到DateTime存储的滴答数。传入一个整数时,最终会添加整数个刻度。

另一方面,我不知道.NET对闰秒做了什么......我怀疑它使用了一个非常简单的模型,它不会打扰它们,让你的代码保持正常。

不要忘记添加时区会增加额外的复杂性 - 在本地添加一天可能会在UTC方面添加超过或少于一天,反之亦然。

答案 3 :(得分:0)

离开午夜你是什么意思?

运行时,第一个代码的最后日期为4/20/2010 12:00:00 AM 我想这就是你的期望。不是吗?

答案 4 :(得分:0)

在您的示例中,我向DateTime变量添加了1天100,000次,但仍以具有午夜时间值的日期结束。似乎没有理由担心。

我确信它们正在四舍五入到时间刻度,这消除了漂移的任何问题。