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


127

谁能解释之间的差异System.DateTime.Now,并System.DateTime.Today在C#.NET?每个可能的利弊。

Answers:


179

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.LocalKind属性。它等效于以下任何一项:

  • 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。该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 feed中找到包对象。一旦添加到项目中,您将发现可以执行以下任一操作:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);

9
那用DateTime.UtcNow代替代替DateTimeOffset.Now呢?
塞缪尔刘氏

5
DateTime.UtcNow如果您可以在应用程序或规范中传达该值采用UTC,则可以接受。(我实际上想称呼字段或属性之类的东西,MyDateUtc而不仅仅是MyDate-但这只是锦上添花。)如果您不能在spec或字段名中传达它,则DateTimeOffset.UtcNow可以用来确保传达零偏移量日期和时间值。
马特·约翰逊·品脱

他们不平等。今天的时间为00:00:00。
詹姆斯·威尔金斯

@JamesWilkins-不知道你在说什么。也是DateTime.Now.Date
马特·约翰逊·品脱

@MattJohnson问题是询问DateTime.Today和DateTime.Now之间的区别,而不是DateTime.Today和DateTime.Now.Date。
David Anderson

85

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

因此,.Now如果您想包括时间,并且.Today只想要日期,请使用它!

.Today 基本上与 .Now.Date


27
...并使用,UtcNow除非您确实想要系统本地时区。(尤其是在Web应用程序上,几乎总是错误的选择。)
Jon Skeet 2013年

22

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

9

DateTime.Today表示当前系统日期,时间部分设置为00:00:00

DateTime.Now表示当前系统日期和时间


2
只是观察... 1.1文档远没有4.0文档详细;链接到vLatest也许更好?
Marc Gravell

3
@megaperlz:您现在链接到4.0,而不是vLatest。通过删除可以建立VLatest链接(v=VS.100)
布赖恩

6

我想到添加这些链接-

回到最初的问题,我用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);
          }
        }

5
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

1

DateTime.TodayDateTime.Now随着时间为零。

请务必注意,DateTime值(表示自0000年1月1日午夜以来经过的滴答数)与该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 Web服务发送时,默认情况下,DateTime值会默认序列化,其中包含时区信息,例如2008-10-31T15:07:38.6875000-05:00,而另一个时区中的计算机仍可以准确知道几点被提及。

因此,使用DateTime.Now和DateTime.Today完全可以。

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.