Eric Bernier
Eric Bernier

Reputation: 489

C# DateTime AddDays Unexpected Offset

I have a very simple DateTime object that is set to the date 01-01-0001. I am supplied a value to add to this DateTime, in days. I am seeing an unexpected offset in my results though, of two days. Let's pretend I print out the results of the AddDays() call, like so:

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

With the value seen above (735768.0) I expect an output of "6/18/2015 12:00:00 AM". However, instead I get "6/20/2015 12:00:00 AM". When I go to the following website and calculate the duration in days between 01-01-0001-->06/18/2015 I get a value of 735,768 days, as expected:

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

Am I doing something wrong, or is there something going on under the hood that I am not aware of?

In case you are wondering, the 735,768 represents the first time value of the data that I am working with. The data is expected to start at 06/18/2015 00:00:00.

Edit: I should note I merely provided that particular website as an example of a conflicting source. Other websites, including the government weather agency I get the data from all give me 06-18-2015. This doesn't mean C# is wrong. I am more so curious as to where this offset came from, and why.

Upvotes: 5

Views: 1546

Answers (5)

Jason W
Jason W

Reputation: 13179

.NET is giving you the "correct" answer - noting that "correct" is assuming a purely gregorian calendar as Andrew Whitaker points out in the comments below and answer above. Andrew's answer is more correct.

A leap year can be defined as divisible by 4, but not divisible by 100 unless it is divisible by 400. Therefore, since 1/1/0001 following those rules, there have been 488 leap days.

Accounting for these leap days, there have been 735,598 days from 1/1/0001 through end of 2014. This leaves us to find day #170 of 2015, which is 6/20/2015 (31 + 28 + 31 + 30 + 31 + 20).

Also, this is not a rounding issue in .NET as some have suggested. Since DateTime.AddDays uses ticks, which are long data types as 64-bit signed ints, no overflows or rounding is occurring.

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)

Upvotes: 4

sudheer reddy
sudheer reddy

Reputation: 3

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..

Upvotes: 0

Andrew Whitaker
Andrew Whitaker

Reputation: 126042

Timeanddate.com is taking into account the calendar change from Julian to Gregorian, which explains the discrepancy.

You can actually see this change occur if you look at the difference between 01/01/1752 and 01/01/1753 on timeanddate.com:

Dates and times. They're crazy!

  • The formula for leap years on the Julian Calendar is "every year divisible by 4". This means that there are way more leap years in timeanddate.com's calculation between year 1 and year 1752, when the Calendar changes. This puts .NET's calculations until 1753 behind by 11 days.
  • Until 1752, England and the east coast of the United States used the Julian Calendar. A consequence of this change is that 1752 was only 355 days long. This calculation is not taken into account by .NET's calculation, and so at this point, .NET's calculation is two days ahead.

According to this answer by Jon Skeet, DateTime essentially uses the Gregorian calendar exclusively. This is why the above subtleties aren't reflected in .NET's calculations.

Upvotes: 5

Trevor Hart
Trevor Hart

Reputation: 1023

If it were leap years it would be a lot more than 2 days, it would be 503 days off if that were the case. There's one of two options in my mind, either A. that calculator you are using online is off a little bit off, or the math that C# is using is inaccurate at that scale. If you do the math yourself you'll see that 735,768 / 365 comes out to a totally irrational number. So my thinking is that the inaccuracies in the math that goes on under the hood can't stay accurate for that many days. This happens ALOT with decimal points, I assume C# is probably truncating the decimal points (rounding it down) and so you're two days off. My guess anyway.

Upvotes: -1

Uri Popov
Uri Popov

Reputation: 2167

From the website "It is 735,768 days from the start date to the end date, but not including the end date". This leads me to think, that you actually need to add 735,767 days since the website counts the start date. But this will only explain the one extra day. Perhaps the website is wrong by one day ? They do have a warning.

Upvotes: 0

Related Questions