5

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.

Eric Bernier
  • 459
  • 1
  • 7
  • 17
  • Did you considerated leap years.? – Vicente Zambrano Jun 25 '15 at 17:19
  • Why not just store the dateTime? Leap years maybe? Try this and see what you get: `TimeSpan diff = new DateTime(2015, 6, 15) - myDateTime;` and see the `diff.TotalDays` value. – Jeffrey Wieder Jun 25 '15 at 17:20
  • 4
    You expect a value of that date why? Because the other website said so, or because you calculated it? What if it's the website that is wrong and not the `AddDays` function? Have you confirmed through multiple sources? – Kritner Jun 25 '15 at 17:23
  • @VicenteZambrano From the DateTime MSDN documentation "The AddDays method takes into account leap years and the number of days in a month when performing date arithmetic." – Eric Bernier Jun 25 '15 at 17:23
  • Not able to reproduce. Your code gives 20/06/2015 00:00:00 in my locale – Steve Jun 25 '15 at 17:23
  • it-IT, however if I try a simple subtraction with two dates the resulting TimeSpan confirms that the difference in days between 20/6/2015 and DateTime.MinValue is 735768 days. – Steve Jun 25 '15 at 17:28
  • 6
    @Steve I think you ***did*** reproduce, you're getting the same date as OP, OP is stating that that date is incorrect. – Kritner Jun 25 '15 at 17:28

5 Answers5

5

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.

Community
  • 1
  • 1
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
4

.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)
Jason W
  • 13,026
  • 3
  • 31
  • 62
  • 2
    The answer is "correct" if you assume the leap year calculations are done with only the Gregorian calendar rules. This could be considered incorrect since multiple calendar systems were used in the date range in question. – Andrew Whitaker Jun 25 '15 at 18:25
0

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.

Uri Popov
  • 2,127
  • 2
  • 25
  • 43
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..
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
-1

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.

Trevor Hart
  • 993
  • 7
  • 26
  • Given that .NET DateTimes are represented internally as the number of 100ns intervals since a given epoch, this seems rather implausible. (Also, years are approximately 365.2425 days long.) – Nathan Tuggy Jun 26 '15 at 00:53
  • "My guess", I didn't say that's what was happening. You get rep taken away for anything you say on this site apparently. A great way to motivate people to want to give input. – Trevor Hart Jun 26 '15 at 01:00
  • Generally, answers are poorly-suited to guessing; for that we have comments. Answers are supposed to be relatively authoritative. – Nathan Tuggy Jun 26 '15 at 01:01
  • A bit of answering from experience or careful research, or some good questions, or a fair amount of useful editing, will all bring you up to 50 soon enough. I do sympathize, but it takes less time to get there than you think. – Nathan Tuggy Jun 26 '15 at 01:04