System.DateTime.Now和System.DateTime.Today之间的区别

任何人都可以解释System.DateTime.NowSystem.DateTime.Today在C#.NET中的区别? 每个可能的优点和缺点。

DateTime.Now返回一个DateTime值,该值包含运行代码的计算机的本地date和时间。 它有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值,该值具有与上述任何一个expression式相同的年份,月份和date组件,但时间组件设置为零。 它的Kind属性中也有DateTimeKind.Local 。 它相当于以下任何一个:

  • 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时间(通过Win32 API中的GetSystemTimeAsFileTime函数),然后将该值转换为本地时区。 (因此DateTime.Now.ToUniversalTime()DateTime.UtcNow更昂贵。)

另外请注意, DateTimeOffset.Now.DateTimeDateTimeOffset.Now.DateTime具有相似的值,但它将具有DateTimeKind.Unspecified而不是DateTimeKind.Local – 这可能会导致其他错误,具体取决于您如何使用它。

所以,简单的答案是DateTime.Today相当于DateTime.Now.Date
但恕我直言 – 你不应该使用任何一个这些,或任何上述等值。

当您要求DateTime.Now ,您正在请求运行代码的计算机的本地日历时钟的值。 但是你回来的东西没有关于那个时钟的任何信息! 你得到的最好的是DateTime.Now.Kind == DateTimeKind.Local 。 但是谁的地方呢? 这些信息一旦你做了任何事情就会丢失,比如存储在数据库中,显示在屏幕上,或者使用Web服务传输。

如果您的本地时区遵循夏令时规则,则不会从DateTime.Now获取该信息。 在模棱两可的时代,例如在“倒退”转换期间,您不会知道两个可能的时刻中哪一个与您使用DateTime.Now检索到的值相对应。 例如,假设您的系统时区设置为Mountain Time (US & Canada)并且您在2013年11月3日凌晨要求提供DateTime.Now 。结果是什么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 -0600 2013-11-03 01:00:00 -0700 。 任何人看着这些价值观都可以说出我的意思。

我在这个主题上写了一篇博客文章。 请阅读 – 对抗DateTime.Now的案例 。

此外,在这个世界上还有一些地方(如巴西),那里的“春季前进”过渡恰好在午夜发生。 时钟从23:59到01:00。 这意味着您在该date获得的DateTime.Today的值不存在! 即使您使用DateTimeOffset.Now.Date ,您也会得到相同的结果,并且仍然存在此问题。 这是因为传统上,在.Net中没有Date对象。 所以不pipe你如何获得价值,一旦你剥夺了时间 – 你必须记住,它并不真正代表“午夜”,即使这是你正在使用的价值。

如果你真的想要一个完全正确的解决scheme,最好的办法是使用NodaTime 。 LocalDate类正确地表示没有时间的date。 您可以获取任何时区的当前date,包括本地系统时区:

 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; 

如果你不想使用野田时间,现在有另一种select。 我已经为.Net CoreFX实验室项目贡献了一个date对象的实现。 您可以在他们的MyGet提要中findSystem.Time包对象。 一旦添加到您的项目中,您会发现您可以执行以下任何操作:

 using System; ... Date localDate = Date.Today; Date utcDate = Date.UtcToday; Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject); 

时间。 .Now包括09:23:12或其他什么; .Today是date部分(当天00:00:00)。

所以使用.Now如果你想包括时间, .Today如果你只是想要的date!

.Today基本上和.Now.Date

DateTime.Now属性返回当前的date和时间,例如2011-07-01 10:09.45310

DateTime.Today属性返回当前时间元素设置为零的date,例如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表示当前系统date,时间部分设置为00:00:00

DateTime.Now表示当前的系统date和时间

我想到了添加这些链接 –

  • DateTime的简要历史 – 由BCL队由安东尼Moore
  • date时间和date时间偏移之间select – 由MSDN
  • 不要忘记SQL Server 2008以后有一个新的数据types为DateTimeOffset
  • .NET Framework包含DateTimeDateTimeOffsetTimeZoneInfotypes,所有这些types都可用于构build使用date和时间的应用程序。
  • 用date和时间MSDN执行算术运算

回到原来的问题,使用reflection器我已经解释了代码的差异

  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.TodayDateTime.Now与时间设置为零。

值得注意的是,表示自0000年1月1日午夜以来stream逝的刻度数的DateTime值与该DateTime值的string表示之间存在差异,该值表示date和时间值文化特定的格式: https : //msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Ticks是.net(本质上是UTC时间)存储的实际时间,其余的只是表示 (对于显示目的来说是重要的)。

如果Kind属性是DateTimeKind.Local它将隐含地包含本地计算机的时区信息。 通过.net Web服务发送时,默认情况下,DateTime值与包含的时区信息(例如2008-10-31T15:07:38.6875000-05:00)序列化,而另一个时区的计算机仍然可以准确知道什么时候是被提及。

所以,使用DateTime.Now和DateTime.Today是完全正确的。

当您开始将string表示与实际值混淆时,通常会遇到麻烦,并尝试修复date时间(未修复)。