Мне было интересно, какие именно принципы работы двух свойств. Я знаю, что вторая универсальна и в основном не касается часовых поясов, но может кто-то объяснить подробно, как они работают и какой из них следует использовать в каком сценарии?
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
Ответ 9
Немного поздно для вечеринки, но я нашел эти две ссылки (4guysfromrolla) очень полезными:
Использование скоординированного универсального времени (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