Может ли кто-нибудь объяснить разницу между System.DateTime.Now
и System.DateTime.Today
в С#.NET? Плюсы и минусы каждого, если это возможно.
Разница между System.DateTime.Now и System.DateTime.Today
Ответ 1
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
, которое имеет те же компоненты year, month и day как любое из приведенных выше выражений, но с компонентами времени, установленными на ноль. Он также имеет 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
? Есть два момента мгновенного времени, представленных этим самым календарем datetime. Если бы я послал это значение кому-то другому, они бы понятия не имели, что я имел в виду. Особенно, если они находятся в часовом поясе, где правила разные.
Лучшее, что вы могли бы сделать, это использовать вместо 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.
Кроме того, в этом мире есть места (например, Бразилия), где переход "spring -forward" происходит точно в полночь. Часы идут с 23:59 до 01:00. Это означает, что значение, которое вы получаете за DateTime.Today
в эту дату, не существует! Даже если вы используете DateTimeOffset.Now.Date
, вы получаете тот же результат, и у вас все еще есть эта проблема. Это потому, что традиционно в .NET не было объекта 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, теперь есть еще один вариант. Я внедрил реализацию объекта только для даты в проект
Ответ 2
Время. .Now
включает в себя 09:23:12 или что-то еще; .Today
- только дата-часть (в 00:00:00 в этот день).
Поэтому используйте .Now
, если вы хотите включить время, и .Today
, если вам нужна дата!
.Today
по существу совпадает с .Now.Date
Ответ 3
Свойство DateTime.Now
возвращает текущую дату и время, например 2011-07-01 10:09.45310
.
Свойство DateTime.Today
возвращает текущую дату с установленными значениями времени, например 2011-07-01 00:00.00000
.
Свойство DateTime.Today
реализовано для возврата DateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
Ответ 4
DateTime.Today представляет текущую системную дату с временной частью, установленной на 00:00:00
и
DateTime.Now представляет текущую системную дату и время
Ответ 5
Я думал о добавлении этих ссылок -
- Краткая история DateTime - Энтони Мур из команды BCL
- Выбор между Datetime и DateTime Offset - по MSDN
- Не забывайте, что SQL Server 2008 имеет новый тип данных как DateTimeOffset
- .NET Framework включает DateTime, DateTimeOffset и TimeZoneInfo, все из которых могут быть использованы для создания приложений которые работают с датами и временем.
- Выполнение арифметических операций с датами и временем-MSDN
Возвращаясь к исходному вопросу, используя 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);
}
}
Ответ 6
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time
Ответ 7
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, когда оно не сломано.