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
in its 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 时间(通过GetSystemTimeAsFileTimeWin32 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
。但这是谁的本地人呢?一旦您对该值执行任何操作,例如将其存储在数据库中、将其显示在屏幕上或使用 Web 服务传输它,该信息就会丢失。
如果您当地的时区遵循任何夏令时规则,您将无法从DateTime.Now
。在模棱两可的情况下,例如在“后退”过渡期间,您将不知道两个可能时刻中的哪一个对应于您检索到的值DateTime.Now
。例如,假设您的系统时区设置为Mountain Time (US & Canada)
你要求DateTime.Now
2013年11月3日凌晨,结果如何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. The 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;
如果您不想使用野田时间,现在还有另一个选择。我向 贡献了一个仅日期对象的实现.Net CoreFX 实验室项目。您可以找到System.Time
MyGet feed 中的 package 对象。添加到项目后,您会发现可以执行以下任一操作:
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);