DateTime.Now против DateTime.UtcNow - PullRequest
       25

DateTime.Now против DateTime.UtcNow

192 голосов
/ 15 сентября 2008

Мне было интересно, каковы принципы работы этих двух свойств. Я знаю, что второй является универсальным и в основном не касается часовых поясов, но кто-то может подробно объяснить, как они работают и какой из них следует использовать в каком сценарии?

Ответы [ 12 ]

305 голосов
/ 15 сентября 2008

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

Я бы порекомендовал использовать DateTime.Now всякий раз, когда вы отображаете дату человеку - так, чтобы им было комфортно с ценностью, которую они видят - это то, что они могут легко сравнить с тем, что они видят на своих часах или Часы. Используйте DateTime.UtcNow, если вы хотите сохранить даты или использовать их для последующих вычислений таким образом (в модели клиент-сервер) ваши вычисления не будут смущены клиентами в разных часовых поясах от вашего сервера или друг от друга.

80 голосов
/ 15 сентября 2008

Это действительно довольно просто, поэтому я думаю, что это зависит от того, какая у вас аудитория и где они живут.

Если вы не используете Utc, вы должны знать часовой пояс человека, которому вы показываете дату и время - в противном случае вы скажете им, что что-то произошло в 3 часа дня в системном или серверном времени. , когда это действительно случилось в 5 часов вечера, где они живут.

Мы используем DateTime.UtcNow, потому что у нас глобальная веб-аудитория, и потому что я бы предпочел не придираться к каждому пользователю, чтобы заполнить форму с указанием часового пояса, в котором он живет.

Мы также отображаем относительное время (2 часа назад, 1 день назад и т. Д.) До тех пор, пока сообщение не станет достаточно старым, чтобы время было «одинаковым» независимо от того, где на Земле вы живете.

29 голосов
/ 21 февраля 2009

Также обратите внимание на разницу в производительности; DateTime.UtcNow где-то примерно в 30 раз быстрее, чем DateTime.Now, потому что внутренне DateTime.Now выполняет множество настроек часового пояса (это легко проверить с помощью Reflector).

Так что не используйте DateTime.Now для измерения относительного времени.

26 голосов
/ 17 сентября 2008

Одна из основных концепций, которую нужно понимать в .NET, заключается в том, что сейчас равно сейчас по всей земле, независимо от того, в каком часовом поясе вы находитесь. Поэтому, если вы загрузите переменную с помощью DateTime.Now или DateTime.UtcNow - назначение идентично. * Ваш DateTime объект знает, в каком часовом поясе вы находитесь, и учитывает его независимо от назначения.

Полезность DateTime.UtcNow оказывается полезной при расчете дат за пределами летнего времени. То есть в местах, которые участвуют в переходе на летнее время, иногда с полудня до полудня следующего дня бывает 25 часов, а иногда между полуднем и полднем следующего дня 23 часа. Если вы хотите правильно определить количество часов от времени A и времени B, вам необходимо сначала перевести каждый из них в их UTC-эквиваленты, прежде чем вычислять TimeSpan.

Это покрыто сообщением в блоге, которое я написал , которое далее объясняет TimeSpan, и включает ссылку на еще более обширную статью MS на эту тему.

* Уточнение: любое назначение будет сохранять текущее время. Если вам нужно было загрузить две переменные, одну из которых через DateTime.Now(), а другую через DateTime.UtcNow(), разница TimeSpan между этими двумя значениями составит миллисекунды, а не часы, если вы находитесь в часовом поясе в часах от GMT. Как отмечено ниже, при печати их значений String будут отображаться разные строки.

14 голосов
/ 09 мая 2015

Это хороший вопрос. Я возрождаю его, чтобы немного подробнее рассказать о том, как .Net ведет себя с различными значениями Kind. Как отмечает @Jan Zich, это на самом деле критически важное свойство, и оно устанавливается по-разному в зависимости от того, используете ли вы Now или UtcNow.

Внутренне дата сохраняется как Ticks, что (в отличие от ответа @Carl Camera) отличается в зависимости от того, используете ли вы Now или UtcNow.

DateTime.UtcNow ведет себя как другие языки. Он устанавливает Ticks на значение по Гринвичу. Он также устанавливает Kind в Utc.

DateTime.Now изменяет значение Ticks на , что было бы, если бы это было ваше время дня в часовом поясе GMT ​​. Он также устанавливает Kind в Local.

Если вы отстали на 6 часов (GMT-6), вы получите время по Гринвичу с 6 часов назад. .Net фактически игнорирует Kind и обрабатывает это время так, как если бы оно было 6 часов назад, хотя это должно быть "сейчас". Это нарушает даже больше, если вы создаете экземпляр DateTime, затем меняете часовой пояс и пытаетесь его использовать.

Экземпляры DateTime с разными значениями «Kind» НЕ совместимы.

Давайте посмотрим на некоторый код ...

    DateTime utc = DateTime.UtcNow;
    DateTime now = DateTime.Now;
    Debug.Log (utc + " " + utc.Kind);  // 05/20/2015 17:19:27 Utc
    Debug.Log (now + " " + now.Kind);  // 05/20/2015 10:19:27 Local

    Debug.Log (utc.Ticks);  // 635677391678617830
    Debug.Log (now.Ticks);  // 635677139678617840

    now = now.AddHours(1);
    TimeSpan diff = utc - now;
    Debug.Log (diff);  // 05:59:59.9999990

    Debug.Log (utc <  now);  // false
    Debug.Log (utc == now);  // false
    Debug.Log (utc >  now);  // true

    Debug.Log (utc.ToUniversalTime() <  now.ToUniversalTime());  // true
    Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() >  now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() -  now.ToUniversalTime());  // -01:00:00.0000010

Как вы можете видеть здесь, сравнения и математические функции не конвертируются автоматически в совместимое время. Timespan должен был составить почти один час, но вместо этого было почти 6. «utc

Вы также можете увидеть «обходной путь», который заключается в простом преобразовании в универсальное время везде, где Kind не совпадает.

Мой прямой ответ на вопрос согласуется с рекомендацией принятого ответа о том, когда использовать каждый из них. Вы всегда должны пытаться работать с DateTime объектами, которые имеют Kind=Utc, кроме как во время ввода-вывода (отображение и анализ). Это означает, что вы почти всегда должны использовать DateTime.UtcNow, за исключением случаев, когда вы создаете объект, просто чтобы отобразить его и сразу отказаться от него.

6 голосов
/ 15 сентября 2008

DateTime понятия не имеет, что такое часовые пояса. Это всегда предполагает, что вы в вашем местном времени. UtcNow означает только «Вычесть мой часовой пояс из времени».

Если вы хотите использовать даты с учетом часового пояса, используйте DateTimeOffset , который представляет дату / время с часовым поясом. Мне пришлось усвоить этот трудный путь.

4 голосов
/ 14 сентября 2012

«Простой» ответ на вопрос:

DateTime.Now возвращает значение DateTime , представляющее текущее системное время (в любом часовом поясе, в котором работает система). Свойство DateTime.Kind будет DateTimeKind.Local

DateTime.UtcNow возвращает значение DateTime , представляющее текущее универсальное координированное время (UTC), которое будет одинаковым независимо от часового пояса системы. Свойство DateTime.Kind будет DateTimeKind.Utc

4 голосов
/ 18 апреля 2009

Просто небольшое дополнение к приведенным выше пунктам: структура DateTime также содержит малоизвестное поле с именем Kind (по крайней мере, я давно об этом не знал). Это в основном просто флаг, указывающий, является ли время местным или UTC; он не указывает реальное смещение от UTC для местного времени. Помимо того факта, что он указывает, с какими намерениями был создан элемент, он также влияет на то, как работают методы ToUniversalTime () и ToLocalTime () .

2 голосов
/ 15 сентября 2011
1 голос
/ 03 октября 2018

DateTime.UtcNow - это универсальная шкала времени, в которой отсутствует летнее время. Таким образом, UTC никогда не меняется из-за летнего времени.

Но DateTime.Now не является непрерывным или однозначным, поскольку изменяется в соответствии с DST. Что означает DateTime.Now, одно и то же время может происходить дважды, оставляя клиентов в замешательстве.

...