C#DateTime AddDays意外偏移

时间:2015-06-25 17:13:26

标签: c# datetime

我有一个非常简单的DateTime对象,设置为日期01-01-0001。我提供了一个值,以天为单位添加到此DateTime。我看到我的结果出现了意想不到的偏差,两天。让我们假装打印出AddDays()调用的结果,如下所示:

DateTime myDateTime = DateTime.Parse("01-01-0001 00:00:00");
Console.WriteLine(myDateTime.AddDays(735768.0));

使用上面显示的值(735768.0),我期望输出" 6/18/2015 12:00:00 AM"。但是,相反,我得到" 6/20/2015 12:00:00 AM"。当我访问以下网站并计算01-01-0001 - > 06/18/2015之间的持续时间时,我得到的值为735,768天,如预期的那样:

http://www.timeanddate.com/date/durationresult.html?m1=01&d1=01&y1=0001&m2=06&d2=18&y2=2015

我做错了什么,或者是否有一些我不知道的事情?

如果您想知道,735,768代表我正在使用的数据的第一次值。预计数据将于06/18/2015 00:00:00开始。

编辑:我应该注意到我只是将该特定网站作为冲突源的示例提供。其他网站,包括政府气象局,我得到的数据都给了我06-18-2015。这并不意味着C#是错误的。我更加好奇这个偏移的来源,以及原因。

5 个答案:

答案 0 :(得分:5)

Timeanddate.com正在考虑从Julian到Gregorian的日历变化,这解释了这种差异。

如果您查看timeanddate.com上01/01/1752 and 01/01/1753之间的区别,您实际上可以看到此更改:

Dates and times. They're crazy!

  • 朱利安日历上的闰年公式为"每年可被4"整除。这意味着,当日历发生变化时,在第1年和第1752年之间的timedate.com计算中有更多的闰年。这使得.NET的计算直到1753年才落后11天。
  • Until 1752,英格兰和美国东海岸使用Julian Calendar。这种变化的结果是1752年只有355天。 .NET的计算没有考虑这个计算,所以此时,.NET的计算是提前两天

根据this answer by Jon SkeetDateTime基本上只使用格里高利历。这就是为什么上述细微之处并未反映在.NET的计算中。

答案 1 :(得分:4)

.NET正在给你“正确”的答案 - 注意“正确”是假设一个纯正的格里高利历,正如安德鲁·惠特克在下面的评论中指出并在上面回答的那样。安德鲁的答案更为正确。

闰年可定义为可被4整除,但不能被100整除,除非它可以被400整除。因此,自那些规则后的1/1/0001,有488个闰日。

从这些闰日算起,从2014年1月1日到2014年底已经有735,598天了。这让我们找到了2015年的第170天,即2015年6月20日(31 + 28 + 31 + 30 + 31 + 20)。

此外,正如一些人所建议的那样,这不是.NET中的四舍五入问题。由于DateTime.AddDays使用滴答,即long数据类型为64位有符号整数,因此不会发生溢出或舍入。

Ticks/day = 864BB (or 8.64 x 10^11)
Tick / (2,015 years) ~ 1.75 x 10^15
Max long = 9,223,372,036,854,775,807 (or 9.22 x 10^18)

答案 2 :(得分:0)

从网站“从开始日期到结束日期为735,768天,但不包括结束日期”。这让我想到,自网站计算开始日期以来,您实际上需要添加735,767天。但这只能解释额外的一天。也许有一天网站出错了?他们确实有警告。

答案 3 :(得分:0)

If you run below code you can find there are only 28 days in Feb for years 100,200 ...... 1900

IF you go through link you will find 29days in Feb for years 100,200....

http://www.timeanddate.com/calendar/?year=100&country=1

Its better not to compare .net date day to Timeanddate.com.

Code:

static void Main(string[] args)
        {          
            for (int i = 001; i <= 2015; i++)
            {
                if (i % 4 == 0)
                {                    
                    if (DateTime.DaysInMonth(i, 2) != 29)
                    {
                        Console.WriteLine("Days {0} in a month feb Year {1}..", DateTime.DaysInMonth(i, 2), i);
                    }
                }
            }
            Console.ReadLine();
        }

OutPut:-

Days 28 in a month feb Year 100..
Days 28 in a month feb Year 200..
Days 28 in a month feb Year 300..
Days 28 in a month feb Year 500..
Days 28 in a month feb Year 600..
Days 28 in a month feb Year 700..
Days 28 in a month feb Year 900..
Days 28 in a month feb Year 1000..
Days 28 in a month feb Year 1100..
Days 28 in a month feb Year 1300..
Days 28 in a month feb Year 1400..
Days 28 in a month feb Year 1500..
Days 28 in a month feb Year 1700..
Days 28 in a month feb Year 1800..
Days 28 in a month feb Year 1900..

答案 4 :(得分:-1)

如果是闰年,那将超过2天,如果是这样的话,那将是503天。在我看来,有两个选项之一,或者A.你在线使用的计算器有点偏离,或者C#正在使用的数学计算是不准确的。如果你自己做数学运算,你会发现735,768/365出现了一个完全无理的数字。所以我的想法是,在引擎盖下进行的数学运算中的不准确性在这么多天内都不能保持准确。这种情况发生在小数点上,我认为C#可能会截断小数点(将其四舍五入),所以你要休息两天。无论如何我的猜测。