Разница между System.DateTime.Now и System.DateTime.Today
Может кто-нибудь объяснить разницу между System.DateTime.Now
а также System.DateTime.Today
в C#.NET? Плюсы и минусы каждого, если это возможно.
8 ответов
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);
Время. .Now
включает в себя 09:23:12 или что-то еще; .Today
только часть даты (в 00:00:00 в этот день).
Так что используйте .Now
если вы хотите включить время, и .Today
если вы просто хотите дату!
.Today
по сути такой же, как .Now.Date
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;
}
}
DateTime.Today представляет текущую системную дату с частью времени, установленной на 00:00:00.
а также
DateTime.Now представляет текущую системную дату и время
Я думал о добавлении этих ссылок -
- Краткая история 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);
}
}
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
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.Now.ToShortDateString()
будет отображаться только часть даты