Может ли кто-нибудь объяснить разницу между System.DateTime.Now
и System.DateTime.Today
в C # .NET? Плюсы и минусы каждого по возможности.
Может ли кто-нибудь объяснить разницу между System.DateTime.Now
и System.DateTime.Today
в C # .NET? Плюсы и минусы каждого по возможности.
Ответы:
DateTime.Now
возвращает DateTime
значение, состоящее из местной даты и времени компьютера, на котором выполняется код. Он DateTimeKind.Local
закреплен за своей Kind
собственностью. Это эквивалентно вызову любого из следующего:
DateTime.UtcNow.ToLocalTime()
DateTimeOffset.UtcNow.LocalDateTime
DateTimeOffset.Now.LocalDateTime
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)
DateTime.Today
возвращает DateTime
значение, которое имеет те же компоненты года, месяца и дня, что и любое из приведенных выше выражений, но с компонентами времени, установленными на ноль. Также имеет DateTimeKind.Local
в своей Kind
собственности. Это эквивалентно любому из следующего:
DateTime.Now.Date
DateTime.UtcNow.ToLocalTime().Date
DateTimeOffset.UtcNow.LocalDateTime.Date
DateTimeOffset.Now.LocalDateTime.Date
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date
Обратите внимание, что внутри системные часы указаны в формате UTC, поэтому при вызове DateTime.Now
они сначала получают время в формате UTC (через GetSystemTimeAsFileTime
функцию в Win32 API), а затем преобразуют значение в местный часовой пояс. (Поэтому DateTime.Now.ToUniversalTime()
дороже чем DateTime.UtcNow
.)
Также обратите внимание, что DateTimeOffset.Now.DateTime
будут иметь аналогичные значения DateTime.Now
, но DateTimeKind.Unspecified
вместо DateTimeKind.Local
- что может привести к другим ошибкам в зависимости от того, что вы с ним делаете.
Итак, простой ответ - это DateTime.Today
эквивалент DateTime.Now.Date
.
Но ИМХО - вы не должны использовать ни один из них, ни какие-либо из вышеперечисленных эквивалентов.
Когда вы запрашиваете DateTime.Now
, вы запрашиваете значение локальных календарных часов компьютера, на котором выполняется код. Но то, что вы получите, не имеет никакой информации о тех часах! Лучшее, что вы получите, это это DateTime.Now.Kind == DateTimeKind.Local
. Но чей это местный? Эта информация теряется, как только вы делаете что-либо со значением, например сохраняете ее в базе данных, отображаете на экране или передаете с помощью веб-службы.
Если ваш местный часовой пояс соответствует правилам перехода на летнее время, вы не получите эту информацию обратно DateTime.Now
. В неоднозначные моменты времени, например, во время «откатного» перехода, вы не будете знать, какой из двух возможных моментов соответствует значению, которое вы получили DateTime.Now
. Например, предположим, что часовой пояс вашей системы установлен, Mountain Time (US & Canada)
а вы запрашиваете его DateTime.Now
в ранние часы 3 ноября 2013 года. Что означает результат 2013-11-03 01:00:00
? Есть два момента мгновенного времени, представленные одной и той же календарной датой и временем. Если бы я отправил это значение кому-то другому, они бы не поняли, что я имел в виду. Особенно, если они находятся в часовом поясе, где действуют другие правила.
Лучшее, что вы могли бы сделать, - это использовать DateTimeOffset
вместо этого:
// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;
Теперь для того же сценария, который я описал выше, я получаю значение 2013-11-03 01:00:00 -0600
до перехода или 2013-11-03 01:00:00 -0700
после перехода. Любой, кто взглянет на эти значения, поймет, что я имел в виду.
Я написал сообщение в блоге на эту самую тему. Прочтите, пожалуйста, - Дело против DateTime.Now .
Кроме того, есть места в этом мире (например, Бразилия), где переход «пружина-вперед» происходит ровно в полночь. Часы идут с 23:59 до 01:00. Это означает, что значение, которое вы получаете DateTime.Today
на эту дату, не существует! Даже если вы используете DateTimeOffset.Now.Date
, вы получаете тот же результат, и у вас все еще есть эта проблема. Это потому, что традиционно Date
в .Net не было объекта. Итак, независимо от того, как вы получаете значение, как только вы отбрасываете время, вы должны помнить, что оно на самом деле не представляет собой «полночь», даже если вы работаете с этим значением.
Если вам действительно нужно полностью правильное решение этой проблемы, лучше всего использовать NodaTime . LocalDate
Класс правильно представляет собой дату без времени. Вы можете получить текущую дату для любого часового пояса, включая часовой пояс локальной системы:
using NodaTime;
...
Instant now = SystemClock.Instance.Now;
DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;
DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;
Если вы не хотите использовать Noda Time, теперь есть другой вариант. Я внес в проект .Net CoreFX Lab реализацию объекта только для даты . Вы можете найти System.Time
объект пакета в их ленте MyGet. После добавления в проект вы обнаружите, что можете выполнять любое из следующих действий:
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
DateTime.UtcNow
приемлемо, если вы можете указать в своем приложении или спецификации, что значение указано в формате UTC. (Мне нравится называть поле или свойство чем-то вроде, MyDateUtc
а не просто MyDate
- но это просто вишенка на торте.) Если вы не можете передать это в спецификации или имени поля, то DateTimeOffset.UtcNow
это можно использовать для обеспечения передачи нулевого смещения со значениями даты и времени.
DateTime.Now.Date
.
Время. .Now
включает 09:23:12 или что-то еще; .Today
только часть даты (в 00:00:00 в этот день).
Так что используйте, .Now
если хотите указать время и .Today
просто хотите дату!
.Today
по сути то же самое, что .Now.Date
UtcNow
если вам действительно не нужен местный часовой пояс системы. (В частности, в веб-приложении это почти всегда неправильный выбор.)
DateTime.Now
Свойство возвращает текущую дату и время, к примеру 2011-07-01 10:09.45310
.
DateTime.Today
Свойство возвращает текущую дату со временем compnents , установленным в ноль, например 2011-07-01 00:00.00000
.
DateTime.Today
Свойство фактически реализуется для возвратаDateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
DateTime.Today представляет текущую системную дату с временной частью, установленной на 00:00:00.
и
DateTime.Now представляет текущую системную дату и время
(v=VS.100)
.
Я подумал о добавлении этих ссылок -
Возвращаясь к исходному вопросу, используя Reflector, я объяснил разницу в коде
public static DateTime Today
{
get
{
return DateTime.Now.Date; // It returns the date part of Now
//Date Property
// returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00)
}
}
private const long TicksPerMillisecond = 10000L;
private const long TicksPerDay = 864000000000L;
private const int MillisPerDay = 86400000;
public DateTime Date
{
get
{
long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks
return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time
}
}
public static DateTime Now
{
get
{
/* this is why I guess Jon Skeet is recommending to use UtcNow as you can see in one of the above comment*/
DateTime utcNow = DateTime.UtcNow;
/* After this i guess it is Timezone conversion */
bool isAmbiguousLocalDst = false;
long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
long ticks2 = utcNow.Ticks + ticks1;
if (ticks2 > 3155378975999999999L)
return new DateTime(3155378975999999999L, DateTimeKind.Local);
if (ticks2 < 0L)
return new DateTime(0L, DateTimeKind.Local);
else
return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
}
}
DateTime.Today
это DateTime.Now
со временем , установленным на нуль.
Важно отметить, что существует разница между значением DateTime, которое представляет количество тактов, прошедших с полуночи 1 января 0000 г., и строковым представлением этого значения DateTime, которое выражает значение даты и времени в формат, зависящий от культуры: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx
DateTime.Now.Ticks
это фактическое время, хранящееся в .net (по существу время в формате UTC), остальное - просто представления (которые важны для целей отображения).
Если Kind
свойство имеет значение, DateTimeKind.Local
оно неявно включает информацию о часовом поясе локального компьютера. При отправке через веб-службу .net значения DateTime по умолчанию сериализуются с включенной информацией о часовом поясе, например, 2008-10-31T15: 07: 38.6875000-05: 00, и компьютер в другом часовом поясе все еще может точно знать, сколько времени упоминается.
Итак, использование DateTime.Now и DateTime.Today совершенно нормально.
Обычно у вас возникают проблемы, когда вы начинаете путать строковое представление с фактическим значением и пытаетесь «исправить» DateTime, когда оно не нарушено.
DateTime.UtcNow
вместоDateTimeOffset.Now
?