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

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

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

Поэтому не используйте DateTime.Now для измерения относительного времени.

Ответ 4

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

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

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

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

Ответ 5

Это хороший вопрос. Я возвращаюсь к нему, чтобы немного подробнее рассказать о том, как .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 & lt; now" должен был быть верным (я даже добавил час, чтобы быть уверенным), но все еще был ложным.

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

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

Ответ 6

DateTime не знает, что такое часовые пояса. Он всегда предполагает, что вы находитесь в свое местное время. UtcNow означает только "вычесть мой часовой пояс из времени".

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

Ответ 7

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

Ответ 8

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

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

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

Ответ 10

DateTime.UtcNow - это непрерывный, однозначный временной масштаб, тогда как DateTime.Now не является непрерывным или однозначным. Основная причина - переход на летнее время, которое не относится к UTC. Таким образом, UTC никогда не перескакивает вперед или назад в час, тогда как местное время (DateTime.Now). И когда он отскакивает назад, одно и то же значение времени происходит дважды.

Ответ 11

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

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

Ответ 12

Если вам требуется местное время для машины, на которой работает ваше приложение (например, CEST для Европы), используйте "Сейчас". Если вы хотите универсальное время - UtcNow. Это просто вопрос ваших предпочтений - возможно, создание локального веб-сайта/автономного приложения, которое вы хотите использовать пользователю времени, - так повлияло его/ее установка часового пояса - DateTime.Now.

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

Ответ 13

Большая разница :) в том, что DateTime.Now не поддерживается в рабочем процессе SharePoint, вы должны использовать DateTime.UtcNow