由于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
}
答案 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次,但仍以具有午夜时间值的日期结束。似乎没有理由担心。
我确信它们正在四舍五入到时间刻度,这消除了漂移的任何问题。