Поведение DateTime.AddYears в високосный год - PullRequest
12 голосов
/ 29 февраля 2012

Может ли кто-нибудь объяснить математическую или просто причину расчетов високосного года в .NET при использовании метода AddYears для DateTime?

  • Если вы возьмете 29 февраля 2012 года и добавите год, вы получите 28 февраля 2013 года, а не 1 марта 2013 года (днем ранее, через год).
  • Если вы добавите один год к 31 января 2012 года, вы получите 31 января 2013 года (такую ​​же дату год спустя).

Я думаю, что большинство людей предположили бы, что "один год с 29.02.leapX равен 01.03.leapX + 1".

Пример:

// Testing with 29th Feb
var now1 = DateTime.Parse("2012-02-29 15:00:00");

var results1 = new DateTime[]
{
    now1.AddYears(1),
    now1.AddYears(2),
    now1.AddYears(3),
    now1.AddYears(4)
};

foreach(var dt in results1)
{
    Console.WriteLine(dt.ToString("s"));
}

// Output:
// 2013-02-28T15:00:00
// 2014-02-28T15:00:00
// 2015-02-28T15:00:00
// 2016-02-29T15:00:00


// Testing with 31st Jan
var now2 = DateTime.Parse("2012-01-31 13:00:00");

var results2 = new DateTime[]
{
    now2.AddYears(1),
    now2.AddYears(2),
    now2.AddYears(3),
    now2.AddYears(4)
};

foreach(var dt in results2)
{
    Console.WriteLine(dt.ToString("s"));
}

// Output:
// 2013-01-31T13:00:00
// 2014-01-31T13:00:00
// 2015-01-31T13:00:00
// 2016-01-31T13:00:00

Ответы [ 2 ]

15 голосов
/ 29 февраля 2012

Я думаю, что большинство людей предположили бы, что "один год с 29.02.leapX равен 01.03.leapX + 1".

Я бы не стал. Я обычно ожидал бы усечение. Это в основном похоже на добавление одного месяца к 30 января - я ожидаю получить последний день февраля. В обоих случаях вы добавляете «большую единицу» (месяц или год), а «меньшая единица» (день) усекается, чтобы соответствовать комбинации год / месяц.

(Вот как Joda Time и Noda Time тоже ведут себя, кстати.)

Как отметил Тим в комментариях, задокументировано тоже так:

Метод AddYears вычисляет итоговый год с учетом високосных лет. Часть месяца и времени дня получающегося объекта DateTime остается такой же, как этот экземпляр.

Таким образом, месяц должен остаться как февраль; очевидно, что год будет меняться в зависимости от того, сколько лет добавляется, поэтому день должен измениться, чтобы оставаться действительным.

2 голосов
/ 29 февраля 2012

По вашему обоснованию 1 марта 2012 г. станет 2 марта 2012 г., если вы добавите год.Если вы добавите эту смену для всех предшествующих високосных лет, то вы увидите, что ваши расчеты будут в значительной степени дрейфовать.Единственным разумным ответом является возвращение 28 февраля для не високосных лет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...