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

Я столкнулся с тем, что может быть високосным годом в.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 23:00:00 PM, 2=2/28/2009 23:00:00 PM
КОНЕЦ: 1=2/28/2012 23:00:00 PM, 2=2/29/2012 23:00:00 PM

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

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

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

3 ответа

Решение

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

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 временем.

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

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

Другие вопросы по тегам