Ошибка високосного года, вызывающая ToUniversalTime (). AddYears (). ToLocalTime ()?

2

Я столкнулся с тем, что может быть високосным годом в обработке .NET DateTime, в частности ToLocalTime(). Вот код, который воспроизводит проблему (я нахожусь в часовом поясе Тихого океана):

DateTime dtStartLocal = DateTime.Parse("2009-02-28T23:00:00.0-08:00");
DateTime dtEndLocal = dtStartLocal.AddYears(3);
DateTime dtStartUtc = dtStartLocal.ToUniversalTime();
DateTime dtEndUtc = dtStartUtc.AddYears(3);
DateTime dtEndLocal2 = dtEndUtc.ToLocalTime();
DateTime dtStartLocal2 = dtStartUtc.ToLocalTime();
Console.WriteLine("START: 1={0}, 2={0}", dtStartLocal, dtStartLocal2);
Console.WriteLine("END  : 1={0}, 2={1}", dtEndLocal, dtEndLocal2);
Console.ReadLine();

Вывод:

НАЧАЛО: 1 = 2/28/2009 11:00:00 PM, 2 = 2/28/2009 11:00:00 PM
END: 1 = 2/28/2012 11:00:00 PM, 2 = 2/29/2012 11:00:00 PM

Обратите внимание, что переменная, которую я сделал ToUniversalTime().AddYears(3).ToLocalTime(), отличается от AddYears(3), она на один день вперед.

Кто-нибудь сталкивался с этим? Если это ожидается, может ли кто-то объяснить логику этого?

ПРИМЕЧАНИЕ. Да, лучший подход заключается в том, чтобы полностью работать в UTC, а не переворачивать между ними. Это не то, что влияет на меня, а на ту особенность, с которой я столкнулся. По сути, я неправильно понял, как работает AddYears(), и теперь я вижу, почему он делает то, что он делает (см. Мой выбранный ответ ниже).

Теги:
datetime
leap-year

3 ответа

9
Лучший ответ

Я думаю, что это работает правильно.

DateTime dtStartUtc = dtStartLocal.ToUniversalTime();

PST - UTC-8. Таким образом, это преобразует время до 1 марта 2009 года, 07:00:00.

DateTime dtEndUtc = dtStartUtc.AddYears(3);

Это добавляет три года к предыдущему времени, поставив его на 1 марта 2012 года, 07:00:00.

DateTime dtEndLocal2 = dtEndUtc.ToLocalTime();

Это преобразует время окончания в PST, которое будет 29 февраля 2012 года, 11:00:00.

Я бы сказал, что это просто побочный эффект преобразования между локальным и UTC-временем.

  • 0
    Хорошее объяснение. Это хороший пример того, почему вы должны использовать дату и время UTC для вашей арифметики даты.
  • 0
    Нет, это хороший пример того, почему арифметика дат в разных часовых поясах плохая. Вы можете выполнять каждую операцию по местному времени и при этом получать тот же результат, что и в UTC. Пока вы последовательны, это не имеет значения.
Показать ещё 2 комментария
0

Это поведение не является неправильным, насколько я могу судить. Когда вы конвертируете местное время в UTC, он эффективно выталкивает его на следующий день; 1 марта. Когда вы добавляете три года, он остается 1 марта. Преобразуйте его обратно в локальное время, и он возвращается к предыдущему дню, который, поскольку 2012 год является високосным годом, составляет 29 февраля.

0

Распечатайте часовой пояс/коэффициент коррекции. Когда вы выполняете .ToUniversialTime(), он существенно добавляет 8 часов с вашего первоначального времени ( "-08: 00" ), который будет установлен в 11:00 следующего дня, начиная с 23:00 28 февраля. Поэтому, когда вы добавляете к нему 3 года, это 11:00 утра 29-го. Если бы вы сделали 2 года, это было бы 1 марта, это не имело никакого отношения к високовому году.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню