it-swarm-tr.com

DateTime.Now vs. DateTime.UtcNow

İki özelliğin çalışma prensibinin tam olarak ne olduğunu merak ediyorum. İkincisinin evrensel olduğunu ve temelde zaman dilimleriyle ilgilenmediğini biliyorum, ancak birisi nasıl çalıştığını ve hangisinin hangi senaryoda kullanılması gerektiğini ayrıntılı olarak açıklayabilir mi?

197
Slavo

DateTime.UtcNow size Greenwich Ortalama Saati saat dilimi olarak da adlandırılan Koordineli Evrensel Saat'te olduğu gibi tarihi ve saati gösterir - temelde Londra İngiltere’deyseniz olduğu gibi yaz boyunca. DateTime.Now , geçerli yerel ayarlarınızda göründüğü gibi tarih ve saati gösterir.

Bir insana bir tarih gösterdiğiniz zaman _DateTime.Now_ kullanmanızı öneririm - bu şekilde gördükleri değerle rahatlarlar - saatlerinde veya saatlerinde gördükleri ile kolayca karşılaştırabilecekleri bir şey. . Tarihleri ​​saklamak istediğinizde _DateTime.UtcNow_ kullanın ya da bunları daha sonraki hesaplamalar için kullanın (bu şekilde bir istemci-sunucu modelinde), hesaplarınız sunucunuzdan veya birbirinizden farklı zaman dilimlerinde müşteriler tarafından karıştırılmaz.

311
Blair Conrad

Ayrıca performans farkına dikkat edin; DateTime.UtcNow DateTime.Now'dan 30 kat daha hızlı bir yerdedir, çünkü dahili DateTime.Now çok fazla zaman dilimi ayarlaması yapar (bunu Reflektör ile kolayca doğrulayabilirsiniz).

Bu yüzden göreceli zaman ölçümleri için DateTime.Now kullanmayın.

29
Magnus Krisell

.NET'te anlaşılması gereken ana kavramlardan biri şimdi şimdi şimdi ne zaman diliminde olursanız olun, dünyanın her yerinde. Yani, _DateTime.Now_ veya _DateTime.UtcNow_ ile bir değişken yüklerseniz - atama aynıdır. * DateTime nesnesinin ne zaman diliminde olduğunu biliyorsun atamadan bağımsız olarak bunu dikkate alır.

_DateTime.UtcNow_ öğesinin yararlılığı, Gün Işığından Yararlanma Saati sınırları içindeki tarihleri ​​hesaplarken kullanışlıdır. Yani, gün ışığından yararlanma zamanına katılan yerlerde, bazen ertesi gün öğlen ile öğlen arasında 25 saat, bazen ertesi gün öğlen ve öğlen arasında 23 saat vardır. A ve B zamanlarının saat sayısını doğru bir şekilde belirlemek istiyorsanız, TimeSpan hesaplamasını yapmadan önce her birini UTC eşdeğerlerine çevirmeniz gerekir.

Bu, TimeSpan'i daha da açıklayan bir yazdığım blog yazısı kapsamındadır ve konuyla ilgili daha kapsamlı bir MS makalesine bağlantı içerir.

* Açıklama: Her iki atama da geçerli saati kaydedecektir. İki değişkeni bir DateTime.Now() ve diğeri DateTime.UtcNow() aracılığıyla yükleyecekseniz, ikisi arasındaki TimeSpan farkı GMT'den bir saat dilimi uzakta olduğunuz varsayılarak saatlerce değil, milisaniye olur. Aşağıda belirtildiği gibi, String değerlerinin yazdırılması farklı dizeler gösterecektir.

26
Carl Camera

Bu iyi bir soru. Net'in farklı Kind değerleri ile nasıl davrandığı hakkında biraz daha ayrıntılı bilgi vermek için canlandırıyorum. @Jan Zich'in işaret ettiği gibi, aslında kritik derecede önemli bir özelliktir ve Now veya UtcNow kullanmanıza bağlı olarak farklı şekilde ayarlanır.

Dahili olarak tarih, Ticks olarak kaydedilir; bu, (@Carl Kameranın yanıtının aksine), Now veya UtcNow kullanmanıza bağlı olarak değişir.

DateTime.UtcNow diğer diller gibi davranır. Ticks değerini GMT tabanlı bir değere ayarlar. Ayrıca Kind - Utc olarak ayarlar.

DateTime.Now, Ticks değerini olarak değiştirirse, GMT saat diliminde günün saatinde olsaydı ne olurdu . Ayrıca Kind - Local olarak ayarlar.

6 saat geri kalıyorsanız (GMT-6), GMT saatini 6 saat öncesinden itibaren alırsınız. Net aslında Kind görmezden geliyor ve bu zamanı 6 saat önceydi, sanki "şimdi" olması gerekiyordu. Bir DateTime örneği oluşturursanız bu daha da kırılır, sonra saat diliminizi değiştirin ve kullanmayı deneyin.

Farklı 'Kind' değerlerine sahip DateTime örnekleri uyumlu değil.

Hadi bazı koda bakalım ...

    DateTime utc = DateTime.UtcNow;
    DateTime now = DateTime.Now;
    Debug.Log (utc + " " + utc.Kind);  // 05/20/2015 17:19:27 Utc
    Debug.Log (now + " " + now.Kind);  // 05/20/2015 10:19:27 Local

    Debug.Log (utc.Ticks);  // 635677391678617830
    Debug.Log (now.Ticks);  // 635677139678617840

    now = now.AddHours(1);
    TimeSpan diff = utc - now;
    Debug.Log (diff);  // 05:59:59.9999990

    Debug.Log (utc <  now);  // false
    Debug.Log (utc == now);  // false
    Debug.Log (utc >  now);  // true

    Debug.Log (utc.ToUniversalTime() <  now.ToUniversalTime());  // true
    Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() >  now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() -  now.ToUniversalTime());  // -01:00:00.0000010

Burada görebileceğiniz gibi, karşılaştırmalar ve matematik işlevleri otomatik olarak uyumlu zamanlara dönüşmez. Timespan neredeyse bir saat olmalıydı, ama bunun yerine neredeyse 6 yaşındaydı.

Ayrıca, Kind aynı olmadığı her yerde basitçe evrensel saate dönüştürmek olan 'çalışmayı' da görebilirsiniz.

Bu soruya doğrudan cevabım, kabul edilen cevapların her birinin ne zaman kullanılacağı konusundaki tavsiyesini kabul eder. Her zaman G/Ç (görüntüleme ve ayrıştırma) dışında Kind=Utc olan DateTime nesnesiyle çalışmayı denemelisiniz . Bu, nesneyi yalnızca görüntülemek ve hemen silmek için kullandığınız durumlar dışında, hemen hemen her zaman DateTime.UtcNow kullanıyor olmanız gerektiği anlamına gelir.

15
Ted Bigham

DateTime saat dilimlerinin ne olduğu konusunda hiçbir fikrimiz yok. Her zaman yerel saatinde olduğunuzu varsayar. UtcNow yalnızca "Zaman dilimimi zamandan çıkar" anlamına gelir.

Saat dilimi duyarlı tarihler kullanmak istiyorsanız, saat dilimi olan bir tarih/saati gösteren DateTimeOffset öğesini kullanın. Bunu zor yoldan öğrenmek zorunda kaldım.

6
Omer van Kloeten

Sorunun "basit" cevabı:

DateTime.Now , geçerli, sistem saatini temsil eden bir DateTime değeri döndürür ( hangi saat diliminde olursa olsun sistemde çalışıyor). DateTime.Kind özelliği şu olacaktır DateTimeKind.Local

DateTime.UtcNow geçerli Evrensel Koordineliği temsil eden bir DateTime değeri döndürür Sistemin saat diliminden bağımsız olarak aynı olacak Saat (aka UTC). DateTime.Kind özelliği şu olacaktır DateTimeKind.Utc

4
PapillonUK

Yukarıda belirtilen noktalara küçük bir ekleme: DateTime yapısı ayrıca Kind (en azından uzun zamandır bilmiyordum) adında az bilinen bir alan içeriyor. Temel olarak sadece zamanın yerel mi yoksa UTC mi olduğunu gösteren bir bayraktır; yerel saatler için UTC'den gerçek ofseti belirtmiyor İlacın hangi niyetlerle yapıldığını göstermesinin yanı sıra, metotların ToUniversalTime () ve ToLocalTime () çalışma şeklini de etkiler.

4
Jan Zich
2
Sorin Comanescu

DateTime.UtcNow, sürekli, tek değerli bir zaman ölçeğidir, DateTime.Now ise sürekli ya da tek değerli değildir. Birincil neden, UTC'ye uygulanmayan Yaz Saati Uygulamasıdır. Bu yüzden UTC hiçbir zaman bir saat ileri veya geri atlamaz, oysa yerel saat (DateTime.Now) bunu yapar. Ve geriye doğru atladığı zaman, aynı zaman değeri iki kere meydana gelir.

1
user1315023

DateTime.UtcNow, Günışığından Yararlanma Zamanını içeren bir evrensel zaman ölçeğidir. Yani UTC, DST nedeniyle hiçbir zaman değişmez.

Ancak DateTime.Now, DST'ye göre değiştiği için sürekli veya tek değerli değil. Bu DateTime demektir. Şimdi, aynı zaman değeri müşterileri şaşkın bir durumda bırakarak iki kez oluşabilir.

1
ChaiVan

Uygulamanızın çalıştığı makine için yerel bir zamana ihtiyacınız olduğunda (Avrupa için CEST gibi), Şimdi kullanın. Evrensel bir zaman istiyorsanız - UtcNow. Bu sadece sizin tercihlerinizden ibarettir - muhtemelen kullanıcının kullandığı zamanı kullanmak isteyeceğiniz yerel bir web sitesi/bağımsız bir uygulama yapmaktır - zaman dilimi ayarından etkilenir - DateTime.Now.

Sadece bir web sitesi için sunucunun saat dilimi ayarı olduğunu unutmayın. Böylece, kullanıcının saatini görüntülüyorsanız, tercih ettiği saat dilimini alın ve saati değiştirin (Utc saatini daha sonra veritabanına kaydedin ve değiştirin) veya UTC'sini belirtin. Bunu yapmayı unutursanız, kullanıcı şöyle bir şey görebilir: dakika önce gönderildi ve daha sonra yakın bir zamanda :)

0
kender