2016-01-08 2 views
4

Это (LINQPad фрагмент):Должен ли DateTime.UtcNow иметь временную шкалу?

DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz").Dump(); 
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz").Dump(); 

Возвращает:

2016-01-08T09:05:04-07:00 // Expected 
2016-01-08T16:05:04-07:00 // Not what I expected 

Учитывая, что второй результат универсального времени, я ожидал, что он вернется 2016-01-08T16:05:04-00:00 (часовой пояс смещение нуля).

Я что-то упустил или это ошибка?

+4

Если вы попробуете это в консольном приложении, оно выдает исключение, так как UtcNow не может использовать указанный формат, поскольку он не имеет зоны ... поэтому формат недействителен для UtcNow, и в LINQPad есть некоторая ошибка, которая игнорируя это. – Gusman

+2

Если вы используете 'DateTimeOffset' вместо' DateTime', это будет правильно. –

+0

Спасибо! Между этими двумя комментариями у меня есть объяснение и обходное решение, и я рад принять либо ответ, если вы хотите его перевести в один. – Anders

ответ

5

Я хочу комбинировать Gusman's и Evan's и создавать аргументы против них, если они позволят мне. Давайте сделаем шаг за шагом.

Должно ли DateTime.UtcNow компенсировать часовой пояс?

Независимо от того, что Kind он (Local, Utc или не указано), DateTime экземпляр не держать любой UTC значение смещения. Период.

Прежде всего, давайте посмотрим на документацию The "zzz" format specifier;

Со значениями DateTime, то «ZZZ» пользовательский формат спецификатор представляет подписал смещение часового пояса локальной операционной системы от UTC, , измеренном в часах и минутах. Он не отражает значение объекта DateTime.Kind объекта . По этой причине формат «zzz» спецификатор не рекомендуется для использования с значениями DateTime.

на основе первых двух смелых предложений, как на результат, порожденный LINQPad является полностью ожидается. Вы можете получить те же результаты (ожидайте даты и времени, конечно,) в Visual Studio.

Просто запустите этот код, как "Start Without Debugging" (Ctrl + F5 )

Console.WriteLine(DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz")); 
Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz")); 

Но что если вы запустите его как "Начать отладку" с (F5)?

Есть два варианта в таком случае, которые зависят от вашего DateTimeInvalidLocalFormat в Managed Debugging Assistants отмечены галочкой или нет. Эти разделы находятся в меню Debug, а затем нажмите Exceptions.

enter image description here

Если эта опция отмечена, вы получите исключение, и он говорит;

UTC DateTime преобразовывается в текст в формате, который только правильно для местного времени. Это может произойти при вызове DateTime.ToString с использованием спецификатора формата 'z', который будет содержать смещение локального часового поясана выходе. В этом случае используйте либо спецификатор формата , обозначающий время UTC, либо используйте строку 'o' , что является рекомендуемым способом сохранения DateTime в тексте.

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

Учитывая, что второй результат универсального времени, я ожидал, что он вернется 2016-01-08T16:05:04-00:00 (часовой пояс смещение нуля).

Как я уже объяснял, zzz спецификатор формата делает не ведут себя, как, что для любого DateTime экземпляра.

Но это ведет себя по-разному для экземпляра DateTimeOffset, который документирован как;

С DateTimeOffset значений, этот спецификатор формата представляет значение DateTimeOffset-х Offset от UTC в часах.

И DateTimeOffset.Now и DateTimeOffset.UtcNow совершенно не соответствует вашим ожиданиям независимо от того, вы работаете в LINQPad или Visual Studio, так как они зарегистрированы как;

Теперь

DateTimeOffset объект, дата и время текущее местное время и чье смещение локального часового пояса это смещение от координированного времени (UTC).

UtcNow

Объект, дата и время всемирное координированное времени (UTC) и которого смещениеTimeSpan.Zero.

Console.WriteLine(DateTimeOffset.Now.ToString("yyyy-MM-ddTHH:mm:sszzz")); 
Console.WriteLine(DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz")); 

будет генерировать

2016-01-08T09:05:04-07:00 
2016-01-08T16:05:04-00:00 

Tl, д-р я думаю, что это не ошибка. LINQPad генерирует правильные результаты точно что это должно быть. В Visual Studio вы может получить исключение, если , что опция имеет галочку или нет в режиме отладки.

+0

Очень тщательный, спасибо! – Anders

+0

@ Эндер Рад помочь. –

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