Разница между System.DateTime.Now и System.DateTime.Today

Может кто-нибудь объяснить разницу между System.DateTime.Now а также System.DateTime.Today в C#.NET? Плюсы и минусы каждого, если это возможно.

8 ответов

Решение

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 (через GetSystemTimeAsFileTimeфункции в Win32 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, Но чей это местный? Эта информация теряется, как только вы что-то делаете со значением, например, сохраняете его в базе данных, отображаете на экране или передаете с помощью веб-службы.

Если ваш местный часовой пояс соответствует правилам перехода на летнее время, вы не получите эту информацию отDateTime.Now, В неоднозначные времена, например, во время "резервного" перехода, вы не будете знать, какой из двух возможных моментов соответствует значению, которое вы получили сDateTime.Now, Например, скажем, ваш системный часовой пояс установлен на Mountain Time (US & Canada)и вы просите DateTime.Nowв первые часы 3 ноября 2013 года. Что означает результат 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. После добавления в ваш проект вы обнаружите, что можете выполнить любое из следующих действий:

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 представляет текущую системную дату и время

Я думал о добавлении этих ссылок -

Возвращаясь к первоначальному вопросу, используя 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);
          }
        }
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, которое представляет количество тиков, прошедших с полуночи 1 января, 0000, и строковым представлением этого значения 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 значения DateTime по умолчанию сериализуются с включенной информацией о часовом поясе, например, 2008-10-31T15:07:38.6875000-05:00, и компьютер в другом часовом поясе все еще может точно знать, какое время ссылаясь.

Таким образом, использование DateTime.Now и DateTime.Today совершенно нормально.

Обычно вы начинаете сталкиваться с проблемами, когда начинаете путать представление строки с фактическим значением и пытаетесь "исправить" DateTime, когда оно не нарушено.

DateTime.Now.ToShortDateString() будет отображаться только часть даты

Другие вопросы по тегам