Вопрос

Как работает преобразование в UTC из стандартного формата DateTime ?

Более конкретно, если я создаю объект DateTime в одном часовом поясе, а затем переключаюсь на другой часовой пояс и запускаю на нем ToUniversalTime () , откуда он узнает преобразование было сделано правильно, и что время все еще точно представлено?

Это было полезно?

Решение

К объекту DateTime не прикреплен неявный часовой пояс. Если вы запустите на нем ToUniversalTime () , он использует часовой пояс контекста, в котором выполняется код.

Например, если я создаю DateTime с эпохи 01.01.1970, он дает мне один и тот же объект DateTime независимо от того, где я нахожусь в мире .

Если я запускаю ToUniversalTime () , когда я запускаю код в Гринвиче, я получаю то же самое время. Если я сделаю это, пока живу в Ванкувере, то получу смещенный объект DateTime , равный -8 часам.

Вот почему важно хранить информацию о времени в вашей базе данных как время UTC, когда вам необходимо выполнить преобразование или локализацию любого вида. Подумайте, не переместилась ли ваша кодовая база на сервер в другом часовом поясе;)

Редактировать: заметка из ответа Джоэла - объекты DateTime по умолчанию печатаются как DateTimeKind.Local . Если вы анализируете дату и устанавливаете ее как DateTimeKind.Utc , тогда ToUniversalTime () не выполняет преобразование.

А вот статья " Кодирование по рекомендациям с датой-временем " и статью о преобразовании дат времени в .Net .

Другие советы

Во-первых, он проверяет, является ли Kind DateTime уже UTC. Если это так, он возвращает то же значение.

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

Часовой пояс содержит достаточно информации для преобразования местного времени в время UTC или наоборот, хотя бывают случаи, когда это неоднозначно или недопустимо. (Существуют локальные времена, которые происходят дважды, и локальные времена, которые никогда не происходят из-за перехода на летнее время.) Правила обработки этих случаев указаны в документация :

  

Если значение экземпляра даты и времени равно   неоднозначное время, этот метод предполагает   что это стандартное время. (An   неоднозначное время - это то, что может отображать   или к стандартному времени или к   летнее время по местному времени   зона) Если дата и время экземпляра   значение является неверным временем, этот метод   просто вычитает местное время из   смещение UTC местного часового пояса к   возврат UTC. (Недопустимое время   что не существует из-за   применение летнего времени   Правила корректировки.)

Возвращаемое значение будет иметь Kind в виде DateTimeKind.Utc , поэтому, если вы вызовете ToUniveralTime , оно не будет применять смещение снова. (Это значительное улучшение по сравнению с .NET 1.1!)

Если вы хотите использовать местный часовой пояс, вы должны использовать < code> TimeZoneInfo , который был введен в .NET 3.5 (есть хакерские решения для более ранних версий, но они не очень хороши). Чтобы представить момент времени, вы должны использовать DateTimeOffset , который был представлен в .NET 2.0SP1, .NET3.0SP1 и .NET 3.5. Однако, это все еще не имеет фактического часового пояса, связанного с ним - только смещение от UTC. Это означает, что вы не знаете, какое местное время будет, например, через час - правила перехода на летнее время могут различаться в зависимости от часовых поясов, в которых в тот или иной момент использовалось одно и то же смещение. TimeZoneInfo предназначен для учета исторических и будущих правил, в отличие от TimeZone , что несколько упрощенно.

По сути, поддержка в .NET 3.5 намного лучше, чем была, но все еще оставляет желать лучшего для правильной календарной арифметики. Кто-нибудь хочет перенести Joda Time на .NET? ;)

Что сказал @womp , кроме того, что он проверяет свойство DateTime's Date, чтобы выяснить, может ли оно уже будет датой UTC.

DateTime.ToUniversalTime удаляет смещение часового пояса местного часового пояса, чтобы нормализовать DateTime к UTC. Если затем использовать DateTime.ToLocalTime для нормализованного значения в другом часовом поясе, смещение часового пояса этого часового пояса будет добавлено к нормализованному значению для правильного представления в этом часовом поясе.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top