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

时间:2011-07-01 08:06:41

标签: c# .net date datetime

任何人都可以解释C#.NET中System.DateTime.NowSystem.DateTime.Today之间的区别吗?如果可能的话,各自的利弊。

8 个答案:

答案 0 :(得分:155)

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时间(通过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。任何看过这些价值观的人都可以说出我的意思。

我写了一篇关于这个主题的博客文章。请阅读 - The Case Against DateTime.Now

此外,在这个世界上有一些地方(如巴西),“春天前进”过渡恰好发生在午夜。时钟从23:59到01:00。这意味着您在该日期DateTime.Today获得的值不存在!即使您使用DateTimeOffset.Now.Date,您也会获得相同的结果,但您仍然拥有此值问题。这是因为传统上,.Net中没有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;

如果您不想使用Noda Time,现在有另一种选择。我已经为.Net CoreFX Lab项目贡献了一个仅限日期的对象的实现。您可以在MyGet Feed中找到System.Time包对象。添加到项目后,您会发现可以执行以下任何操作:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);

答案 1 :(得分:82)

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

如果您想要包含时间,请使用.Now;如果您只想要日期,请使用.Today

.Today.Now.Date

基本相同

答案 2 :(得分: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;
  }
}

答案 3 :(得分:9)

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

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

答案 4 :(得分: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 :(得分: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

答案 6 :(得分:1)

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

值得注意的是,DateTime值(表示自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网络服务发送时,默认情况下,日期时间值序列化,包括时区信息,例如, 2008-10-31T15:07:38.6875000-05:00,另一个时区的计算机仍然可以准确知道被引用的时间。

因此,使用DateTime.Now和DateTime.Today完全没问题。

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

答案 7 :(得分:-1)

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