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

有人能解释一下 C # .NET 中 System.DateTime.NowSystem.DateTime.Today的区别吗? 如果可能的话,各自的优缺点。

154556 次浏览

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

因此,如果你想包括时间使用 .Now,如果你只想要日期使用 .Today

.Today基本上与 .Now.Date相同

Today 表示当前系统日期,time 部分设置为00:00:00

还有

现在 表示当前系统的日期和时间

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 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

我想添加这些链接-

回到最初的问题,使用反射器我已经解释了代码的差异

 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.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值,该值具有与上述任何表达式相同的年、月和日分量,但是时间分量设置为零。它的 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.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),而您要求在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 -0700。任何看到这些值的人都能明白我的意思。

我写了一篇关于这个主题的博客文章,请阅读。

此外,在世界上的一些地方(如巴西) ,“春季前进”的过渡恰好发生在午夜。时钟从23:59到01:00。这意味着在那个日期得到的 DateTime.Today值是 根本不存在!,即使使用 DateTimeOffset.Now.Date,也会得到相同的结果,并且仍然存在这个问题。这是因为传统上,在。网。所以不管你是如何得到这个值的,一旦你去掉了时间-你必须记住它并不真的代表“午夜”,即使这是你正在处理的值。

如果您真的想要这个问题的完全正确的解决方案,最好的方法是使用 NodaTimeLocalDate类正确地表示一个没有时间的日期。您可以得到任何时区的当前日期,包括本地系统时区:

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 实验室项目贡献了一个仅限于日期的对象的实现。您可以在它们的 MyGet 提要中找到 System.Time包对象。一旦添加到您的项目中,您将发现您可以执行以下任何操作:

using System;
...


Date localDate = Date.Today;


Date utcDate = Date.UtcToday;


Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);

DateTime.TodayDateTime.Now,时间设置为0。

需要注意的是,DateTime 值表示1,000年1月1日午夜以来已经过去的节拍数,而 DateTime 值的字符串表示形式表示特定于文化特性的格式的日期和时间值,两者之间存在差异: Https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

存储的实际时间。Net (基本上是 UTC 时间) ,其余的只是 申述(这对于显示很重要)。

如果 Kind属性为 DateTimeKind.Local,则 毫无疑问包含本地计算机的时区信息。当发送一个。在 net Web 服务中,DateTime 值默认是序列化的,其中包含时区信息,例如2008-10-31T15:07:38.6875000-05:00,并且位于另一个时区的计算机仍然可以准确地知道所引用的时间。

因此,使用日期时间。现在和日期时间。今天是完全可以的。

当您开始将字符串表示与实际值混淆并试图“修复”DateTime 时,通常会遇到麻烦。

DateTime.Now.ToShortDateString()将只显示日期部分