2009-03-02 3 views
2

Я столкнулся с тем, что может быть високосным годом в обработке NET DateTime, в частности ToLocalTime(). Вот код, который воспроизводит эту проблему (я в Тихоокеанском часовом поясе):Ошибка в високовом году с использованием ToUniversalTime(). AddYears(). 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(); 

Выход есть:

START: 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(), и теперь я вижу, почему он делает то, что он делает (см. Мой выбранный ниже ответ).

ответ

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. Пока вы последовательны, это не имеет значения. – Whatsit

+0

@Whatsit: в этом случае да, но если мы добавим DST в микс, UTC - единственный разумный способ –

0

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

0

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

 Смежные вопросы

  • Нет связанных вопросов^_^