2015-06-25 2 views
5

У меня очень простой объект DateTime, который установлен на дату 01-01-0001. Я получаю значение, добавляемое в это DateTime, через несколько дней. Я вижу неожиданное смещение в моих результатах, хотя и двух дней. Давайте представим, что я распечатать результаты AddDays() вызов, например, так:C# 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 представляет собой первое значение данных, с которыми я работаю. Ожидается, что данные начнутся с 18.06.2012 00:00:00.

Редактировать: Я должен отметить, что я просто представил этот конкретный веб-сайт в качестве примера конфликтующего источника. Другие сайты, в том числе правительственное агентство по погоде, я получаю данные от всех, дайте мне 06-18-2015. Это не означает, что C# неверен. Мне более любопытно, откуда взялось это смещение, и почему.

+0

Вы рассмотренный високосными.? –

+0

Почему бы не просто сохранить дату? Может быть, високосные годы? Попробуйте это и посмотрите, что вы получаете: 'TimeSpan diff = new DateTime (2015, 6, 15) - myDateTime;' и см. Значение 'diff.TotalDays'. –

+4

Вы ожидаете значения этой даты? Потому что другой сайт сказал так, или потому, что вы его рассчитали? Что делать, если это неправильный сайт, а не функция «AddDays»? Вы подтвердили через несколько источников? – Kritner

ответ

5

Timeanddate.com принимает во внимание изменение календаря с Джулианом на Григорианский, что объясняет расхождение.

Вы можете увидеть это изменение произойдет, если вы посмотрите на разницу между 01/01/1752 and 01/01/1753 на timeanddate.com:

Dates and times. They're crazy!

  • Формула високосных по Юлианскому календарю является «каждый год делится на 4" . Это означает, что есть еще больше високосных лет в расчете timeanddate.com между 1 и 1752 годом, когда календарь меняется. Это приводит вычисления .NET до 1753 года на 11 дней.
  • Until 1752, Англия и восточное побережье США использовали Julian Calendar. Следствием этого изменения является то, что 1752 года составляли всего 355 дней. Этот расчет не учитывается при расчете .NET, поэтому на этом этапе расчет .NET составляет два дня впереди.

Согласно this answer by Jon Skeet, DateTime использует исключительно григорианский календарь. Вот почему приведенные выше тонкости не отражены в вычислениях .NET.

0

От веб-сайта «Это 735 768 дней с даты начала до конца, но не включая дату окончания». Это заставляет меня думать, что вам действительно нужно добавить 735 767 дней, так как веб-сайт учитывает дату начала. Но это объяснит только один дополнительный день. Возможно, на один день сайт ошибается? У них есть предупреждение.

-1

Если бы это были високосные годы, было бы намного больше, чем через 2 дня, это было бы 503 выходных дней, если бы это было так. На мой взгляд, есть один из двух вариантов: либо, что калькулятор, который вы используете в сети, немного выключен, или математика, используемая C#, неточна в этом масштабе. Если вы сделаете математику самостоятельно, вы увидите, что 735 768/365 выходит на совершенно иррациональное число. Поэтому я считаю, что неточности в математике, которые проходят под капотом, не могут оставаться точными в течение многих дней. Это происходит с использованием десятичных точек, я предполагаю, что C#, вероятно, усекает десятичные точки (округляя его), и поэтому у вас два выходных дня. Я все равно думаю.

+0

Учитывая, что .NET DateTimes представлены внутренне как число интервалов в 100 нс с той или иной эпохи, это кажется довольно неправдоподобным. (Также, лет примерно 365.2425 дней.) –

+0

«Мое предположение», я не сказал, что это происходит. По-видимому, вы получаете репутацию за все, что вы говорите на этом сайте. Отличный способ побудить людей хотеть внести свой вклад. –

+0

Как правило, ответы плохо подходят для угадывания; для этого у нас есть комментарии. Ответы должны быть относительно авторитетными. –

4

.NET дает вам «правильный» ответ - отметив, что «правильный» принимает чисто грегорианский календарь, как указывает Эндрю Уайтекер в комментариях ниже и отвечает выше. Ответ Эндрю вернее.

Високосный год может быть определен как делимый на 4, но не делится на 100, если он не делится на 400. Поэтому, начиная с 1/00/0101 после этих правил, было 488 високосных дней.

Учет этих високосных дней составил 735 598 дней с 01.01.00 по конец 2014 года. Это позволяет нам найти день № 170 2015 года, который составляет 6/20/2015 (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

При запуске ниже код, который вы можете найти там только 28 дней в феврале в течение многих лет 100200 ...... 1900

Если вы идете через ссылку вы найдете 29days в феврале в течение многих лет 100,200 .. ..

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

Его лучше не сравнивать дата .net день timeanddate.com.

Код:

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(); 
     } 

Выход: -

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.. 
Смежные вопросы