系统之间的差异.日期时间.现在和系统.日期时间.今天



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

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
但是IMHO-你不应该使用其中任何一个,或者上面的任何等价物

当你询问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。任何一个看到这些价值观的人都能明白我的意思。

我写了一篇关于这个主题的博客文章。请阅读-反对DateTime的案例。现在

此外,世界上有些地方(如巴西)的"春季前进"过渡正好发生在午夜。时钟从23:59到01:00。这意味着您在该日期获得的DateTime.Today的值不存在即使你使用DateTimeOffset.Now.Date,你也会得到同样的结果,而且你仍然有这个问题。这是因为传统上,中没有Date对象。网因此,无论你如何获得价值,一旦你去掉时间,你必须记住,它并不真正代表"午夜",即使这是你正在使用的价值。

如果你真的想要一个完全正确的解决方案,最好的方法是使用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实验室项目。您可以在他们的MyGet提要中找到System.Time包对象。一旦添加到你的项目中,你会发现你可以做以下任何一项:

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

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

所以,如果你想包含时间,请使用.Now,如果你只想包含日期,请使用.Today

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

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.Today表示当前系统日期,时间部分设置为00:00:00

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

  • DateTime简史-BCL团队Anthony Moore
  • 在日期时间和日期时间偏移之间进行选择-MSDN
  • 不要忘记SQL server 2008以后的版本有一个新的数据类型DateTimeOffset
  • .NET Framework包括DateTimeDateTimeOffsetTimeZoneInfo类型,所有这些类型都可用于构建应用程序工作与日期和时间
  • 使用日期和时间MSDN执行算术运算

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

 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.Today是时间设置为零的DateTime.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.Tay完全可以。

当您开始将字符串表示与实际值混淆,并试图在DateTime未损坏的情况下"修复"它时,您通常会遇到麻烦。

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

最新更新