System.DateTime.Now ve System.DateTime.Today arasındaki fark


127

Herkes arasındaki farkı açıklayabilir System.DateTime.Nowve System.DateTime.TodayC # .NET içinde? Mümkünse her birinin artıları ve eksileri.

Yanıtlar:


179

DateTime.NowDateTimeKodun çalıştığı bilgisayarın yerel tarih ve saatinden oluşan bir değer döndürür . Bu gelmiştir DateTimeKind.Localonun atanan Kindözelliği. Aşağıdakilerden herhangi birini aramakla eşdeğerdir:

  • DateTime.UtcNow.ToLocalTime()
  • DateTimeOffset.UtcNow.LocalDateTime
  • DateTimeOffset.Now.LocalDateTime
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)

DateTime.TodayDateTimeYukarıdaki ifadelerden herhangi biriyle aynı yıl, ay ve gün bileşenlerine sahip, ancak zaman bileşenleri sıfır olarak ayarlanmış bir değer döndürür . Ayrıca vardır DateTimeKind.Localonun içinde Kindmülkiyet. Aşağıdakilerden herhangi birine eşdeğerdir:

  • 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

Dahili olarak, sistem saatinin UTC cinsinden olduğunu unutmayın; bu nedenle, DateTime.Nowonu ilk aradığınızda UTC saatini alır ( GetSystemTimeAsFileTimeWin32 API'deki işlev aracılığıyla ) ve ardından değeri yerel saat dilimine dönüştürür. (Bu nedenle DateTime.Now.ToUniversalTime()daha pahalıdır DateTime.UtcNow.)

Ayrıca, DateTimeOffset.Now.DateTimebunun ile benzer değerlere sahip olacağını DateTime.Now, ancak bunun DateTimeKind.Unspecifiedyerine sahip olacağını unutmayın - bununla DateTimeKind.Localne yaptığınıza bağlı olarak başka hatalara yol açabilir.

Yani, basit cevap DateTime.Todayşuna eşdeğerdir DateTime.Now.Date.
Ancak IMHO - Bunlardan birini veya yukarıdaki eşdeğerlerini kullanmamalısınız.

İstediğinizde DateTime.Now, kodun çalıştığı bilgisayarın yerel takvim saatinin değerini soruyorsunuz. Ama geri aldığın şey o saat hakkında hiçbir bilgi içermiyor! Aldığın en iyi şey bu DateTime.Now.Kind == DateTimeKind.Local. Ama bu kimin yerel? Bir veri tabanında saklamak, ekranda göstermek veya bir web hizmeti kullanarak iletmek gibi değerle ilgili herhangi bir şey yaptığınız anda bu bilgiler kaybolur.

Yerel saat diliminiz herhangi bir yaz saati uygulaması kuralına uyuyorsa, bu bilgiyi buradan geri alamazsınız DateTime.Now. "Geri dönüş" geçişi gibi belirsiz zamanlarda, iki olası andan hangisinin geri aldığınız değere karşılık geldiğini bilemezsiniz DateTime.Now. Örneğin, sistem saat diliminizin olarak ayarlandığını Mountain Time (US & Canada)ve DateTime.Now3 Kasım 2013'ün erken saatlerinde 2013-11-03 01:00:00istediğinizi varsayalım. Sonuç ne anlama geliyor? Aynı takvim tarih saati ile temsil edilen iki anlık zaman anı vardır. Bu değeri bir başkasına gönderirsem, hangisini kastettiğime dair hiçbir fikirleri olmazdı. Özellikle de kuralların farklı olduğu bir zaman dilimindeyse.

Yapabileceğiniz en iyi şey DateTimeOffsetbunun yerine kullanmak olacaktır :

// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;

Şimdi, yukarıda anlattığım aynı senaryo için, değeri 2013-11-03 01:00:00 -0600geçişten önce veya 2013-11-03 01:00:00 -0700geçişten sonra alıyorum . Bu değerlere bakan herkes ne demek istediğimi anlayabilir.

Tam da bu konuda bir blog yazısı yazdım. Lütfen okuyun - DateTime.Now Karşısındaki Durum .

Ayrıca, bu dünyada (Brezilya gibi) "ileriye doğru ilkbahar" geçişinin tam olarak Gece Yarısında gerçekleştiği bazı yerler vardır. Saatler 23:59 ile 01:00 arasındadır. Bu DateTime.Today, o tarihte aldığınız değerin mevcut olmadığı anlamına gelir ! Kullansanız bile DateTimeOffset.Now.Dateaynı sonucu alıyorsunuz ve hala bu sorunu yaşıyorsunuz. Çünkü geleneksel olarak Date.Net'te nesne diye bir şey yoktur . Dolayısıyla, değeri nasıl elde ettiğinizden bağımsız olarak, zamanı bir kez çıkardığınızda - çalıştığınız değer bu olsa bile, bunun "gece yarısını" temsil etmediğini hatırlamanız gerekir.

Bu soruna gerçekten tam olarak doğru bir çözüm istiyorsanız, en iyi yaklaşım NodaTime kullanmaktır . LocalDateSınıf düzgün bir süre verilmeksizin bir tarih temsil eder. Yerel sistem saat dilimi de dahil olmak üzere herhangi bir saat dilimi için geçerli tarihi alabilirsiniz:

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'ı kullanmak istemiyorsanız, şimdi başka bir seçenek var. Net CoreFX Lab projesine yalnızca tarih içeren bir nesnenin uygulanmasına katkıda bulundum . Sen bulabilirsiniz System.Timeonların MyGet yemlerde paket nesnesi. Projenize eklendikten sonra, aşağıdakilerden herhangi birini yapabileceğinizi göreceksiniz:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);

9
Bunun DateTime.UtcNowyerine kullanımı ne olacak DateTimeOffset.Now?
Samuel Liew

5
DateTime.UtcNowUygulamanızda belirtebilirseniz veya değerin UTC olarak belirtilmesi kabul edilebilir. (Alan veya mülke aslında MyDateUtcsadece MyDate- ama bu sadece pastanın üzerine krema gibi bir şey demeyi seviyorum .) Spesifikasyon veya alan adında DateTimeOffset.UtcNowbunu aktaramıyorsanız, sıfır ofsetinin aktarılmasını sağlamak için kullanılabilir. tarih ve saat değerleri ile.
Matt Johnson-Pint

Eşit değiller. Bugünün saati 00:00:00.
James Wilkins

@JamesWilkins - Neye ulaştığınızdan emin değilim. Öyle DateTime.Now.Date.
Matt Johnson-Pint

@MattJohnson Soru DateTime.Today ve DateTime.Now arasındaki farkı soruyor, DateTime.Today ve DateTime.Now.Date değil.
David Anderson

85

Zaman. .Now09:23:12 veya her neyse içerir; .Todayyalnızca tarih bölümüdür (o gün saat 00:00:00).

Öyleyse .Now, saati eklemek .Todayistiyorsanız ve sadece tarihi istiyorsanız kullanın!

.Today esasen aynıdır .Now.Date


27
... ve sistemin yerel saat dilimini gerçekten istemediğiniz UtcNowsürece kullanın . (Özellikle bir web uygulamasında bu neredeyse her zaman yanlış seçimdir.)
Jon Skeet

22

DateTime.NowMülkiyet örneğin geçerli tarih ve saati döndürür 2011-07-01 10:09.45310.

DateTime.TodayMülkiyet örneğin sıfıra ayarlanan saat bileşenlere sahip geçerli tarih döndürür 2011-07-01 00:00.00000.

DateTime.TodayMülkiyet aslında dönüş için uygulanır DateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}

9

DateTime.Today , saat bölümü 00:00:00 olarak ayarlanmış mevcut sistem tarihini temsil eder.

ve

DateTime.Now mevcut sistem tarihini ve saatini temsil eder


2
sadece bir gözlem ... 1.1 dokümantasyonu 4.0 dokümantasyonundan çok daha az detaylıdır; vLatest'e bağlanmak belki daha iyidir?
Marc Gravell

3
@megaperlz: Şu anda vLatest yerine 4.0'a bağlanıyorsunuz. VLatest bağlantıları (v=VS.100),.
Brian

6

Bu bağlantıları eklemeyi düşündüm -

Orijinal soruya dönersek, Reflektör kullanarak koddaki farkı açıkladım

 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.Todayolduğu DateTime.Nowsıfıra ayarlanmış zamanla.

1 Ocak gece yarısından bu yana geçen onay işaretlerinin sayısını temsil eden bir DateTime değeri ile bir tarih ve saat değerini ifade eden bu DateTime değerinin dize gösterimi arasında bir fark olduğuna dikkat etmek önemlidir. kültüre özgü biçim: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Ticks.net tarafından depolanan gerçek zamandır (esasen UTC saati), geri kalanı yalnızca temsillerdir (görüntüleme amaçları için önemlidir).

Eğer Kindbir özelliktir DateTimeKind.Localbu örtük yerel bilgisayarın saat dilimi bilgilerini içerir. .Net web hizmeti üzerinden gönderirken, DateTime değerleri varsayılan olarak saat dilimi bilgileriyle birlikte serileştirilir, ör. 2008-10-31T15: 07: 38.6875000-05: 00 ve başka bir saat dilimindeki bir bilgisayar hala saatin tam olarak ne olduğunu bilebilir başvuruluyor.

Yani, DateTime.Now ve DateTime.Today kullanmak mükemmel bir şekilde tamam.

Dize gösterimini gerçek değerle karıştırmaya başladığınızda ve bozuk olmadığı zaman DateTime'ı "düzeltmeye" çalıştığınızda genellikle sorun yaşarsınız.


-1

DateTime.Now.ToShortDateString() sadece tarih bölümünü gösterecek

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.