DateTime.Now ve DateTime.UtcNow karşılaştırması


226

İki mülkün nasıl çalıştığı ilkelerinin tam olarak ne olduğunu merak ediyorum. İkincisinin evrensel olduğunu ve temel olarak 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?


1
çok geç olabilir ama bu bloga işaret etmek istiyorum: blog.angeloflogic.com/2013/10/…
Kai Wang

küçük tezgah işareti rextester.com/QRDR82396
Daniel B

Yanıtlar:


347

DateTime.UtcNow , tarih ve saati Greenwich Ortalama Saati saat dilimi olarak da adlandırılan Eşgüdümlü Evrensel Saat'teki gibi söyler - temelde Londra İngiltere'sindeymişsiniz gibi, ancak yaz boyunca değil. DateTime.Now , geçerli yerel ayarınızdaki birine göründüğü şekliyle tarihi ve saati verir.

DateTime.NowBir insan için bir tarih görüntülerken kullanmanızı öneririm - bu şekilde gördükleri değerden rahat olurlar - saatlerinde veya saatlerinde gördükleriyle kolayca karşılaştırabilecekleri bir şey. DateTime.UtcNowTarihleri ​​saklamak veya daha sonraki hesaplamalar için kullanmak istediğinizde kullanın (bu şekilde bir istemci-sunucu modelinde) hesaplamalarınız sunucunuzdan veya birbirinden farklı saat dilimlerindeki istemciler tarafından karıştırılmaz.


84
mükemmel bir nokta - tarihleri ​​bir veritabanında veya dosyada saklarken kesinlikle UTC'de saklayın!
Jeff Atwood

15
Tarihleri ​​UTC'de veritabanında saklamak istediğinizde, veritabanının açık saat dilimleri vermeyen tarihlere kendi saat dilimini eklemediğinden emin olmanız gerektiğini unutmayın. DateTime öğesinin her zaman geçerli saat dilimini kullanacağını unutmayın.
Omer van Kloeten

@OmervanKloeten çok iyi bir noktaya değiniyor. IIS ve SQL sunucunuz farklı saat dilimlerinde olsa bile tarihleri ​​doğru bir şekilde saklamak ve almak için bunun için zarif bir 'çok yönlü' çözüm olup olmadığını merak ediyorum.
TheGeekZn

1
@ JoshYates1980 Evet sadece DateTime.UtcNow.AddYears (1)
CathalMF

3
NodaTime kullanın - zaman hakkında daha yararlı bir şekilde
düşünmenizi

86

Gerçekten oldukça basit, bu yüzden kitlenizin ne olduğuna ve nerede yaşadıklarına bağlı olduğunu düşünüyorum.

Eğer UTC kullanmazsanız, sen gerekir aksi takdirde gerçekten 5 PM nerede meydana geldi sistem veya sunucu süresi 3 de oldu onlara bir şeyler söyleyecektir - Eğer tarihleri ve saatleri görüntülediğiniz kişinin dilimini biliyorum yaşarlar.

DateTime.UtcNowKüresel bir web izleyicimiz olduğu için ve her kullanıcıyı hangi saat diliminde yaşadıklarını gösteren bir form doldurmak için çağırmamayı tercih ettiğimiz için kullanıyoruz .

Ayrıca, dünyanın neresinde yaşıyor olursanız olun, zamanın "aynı" olacağı zamana kadar olan zamana kadar göreceli süreleri (2 saat önce, 1 gün önce, vb.) Görüntüleriz.


Ayrıca DateTime.UtcNow depolamak da sadece doğru tarih almak için 2 tarih ile hesaplama yapıldığında gerekli ikinci istiyorum. Sadece bir RegisterAt Tarih göstermek zorunda zaman o zaman Datetime.Now yeterlidir.
Elisabeth

36

Ayrıca performans farkına dikkat edin; DateTime.UtcNowyere dönünce 30 sonra kat daha hızlı DateTime.Nowdahili çünkü DateTime.Nowzaman dilimi ayarlamaları çok (kolayca Reflektör doğrulayabilirsiniz) yapıyor.

Dolayısıyla DateTime.Nowgöreceli zaman ölçümleri için KULLANMAYIN .


Bana sadece acı veren bir yolculuk aldı UtcNow daha iyi bir performansa sahip olduğunu bilmek ve sadece mysql tarihlerini kaydetmek ve utc olduğunu varsayarak ve tarihe bağlı ekranlar UtcNow ile karşılaştırmak bu küresel saat dilimi sorunları basitleştirir
Diin

29

.NET'te anlaşılması gereken temel bir kavram, şu anda hangi saat diliminde olursanız olun , artık tüm dünyada olduğu. Yani DateTime.Nowveya ile bir değişken DateTime.UtcNowyüklerseniz atama aynıdır. * DateTimeNesneniz hangi saat diliminde olduğunuzu bilir ve görevden bağımsız olarak bunu dikkate alır.

DateTime.UtcNowYaz Saati Uygulaması sınırları içindeki tarihleri ​​hesaplarken kullanışlılığı işe yarar . Yani, yaz saati uygulamasına katılan yerlerde, bazen ertesi gün öğleden öğlene kadar 25 saat, bazen de ertesi gün öğlen ile öğlen arasında 23 saat vardır. A ve B zamanlarından saat sayısını doğru bir şekilde belirlemek istiyorsanız, hesaplanmadan önce her birini UTC eşdeğerlerine çevirmeniz gerekir TimeSpan.

Bu, daha fazla açıklayan ve konuyla ilgili daha kapsamlı bir MS makalesine bir bağlantı içeren bir blog yazısı ile kaplıdır TimeSpan.

* Açıklama: Her iki atama da geçerli saati saklar. Eğer iki değişken aracılığıyla birini yüklemek için olsaydı DateTime.Now()ve üzerinden diğer sen saat uzaklıkta GMT bir saat dilimine göredir varsayarak milisaniye, saat olurdu ikisi arasındaki farka. Aşağıda belirtildiği gibi, değerlerini yazdırmak farklı dizeler görüntüler.DateTime.UtcNow()TimeSpanString


1
"DateTime.Now veya DateTime.UtcNow ile bir değişken yükleyin - atama aynı" ile ilgili: Bunun açıklığa kavuşturulması gerekebilir mi? Ben burada EDT saat diliminde (UTC -4) otururken, DateTime.UtcNow ve DateTime.Now sırasıyla iki değişken atadı ve sonra ToString () ile değerlerini yazdırdı. Görüntülenen değerler 4 saat arayla idi - "özdeş" değil.
Jon Schneider

2
@JonSchneider, haklı olduğuna inanıyorum. "Ödev aynı" ifadesi doğru değil. ToString () muhtemelen çünkü testine en iyi yol değildir olabilir (Java yaptığı gibi) farklı eşit tarihleri görüntüler. Karşılaştırma fonksiyonları daha iyi bir testtir ve gerçekten eşit olmadıklarını gösterir.
Ted Bigham

"Özdeş" ifadem için açıklama: Bir değişkeni DateTime.Now ile diğerini DateTime.UtcNow ile yükleyin ve ardından TimeSpan farkını yazdırın. Fark, milisaniye olacak ve GMT'den saatlerce uzakta olduğunuzu varsayarak saat değil.
Carl Camera

18

Bu iyi bir soru. .Net'in farklı Kinddeğerlerle nasıl davrandığı hakkında biraz daha ayrıntılı bilgi vermek için canlandırıyorum . @Jan Zich'in de belirttiği gibi, aslında kritik öneme sahip bir özelliktir Nowveya kullanmanıza bağlı olarak farklı ayarlanmıştır UtcNow.

Dahili olarak tarih, Ticks(@Carl Camera yanıtının aksine) Nowveya kullanmanıza bağlı olarak farklı olarak kaydedilir UtcNow.

DateTime.UtcNowdiğer diller gibi davranır. TicksGMT tabanlı bir değere ayarlar . Ayrıca ayarlar Kindiçin Utc.

DateTime.NowGMT saat diliminde günün saati olsaydıTicks değeri olacağı değere değiştirir . Ayrıca ayarlar Kindiçin Local.

6 saat gerideyseniz (GMT-6), GMT süresini 6 saat öncesinden alacaksınız. .Net Kind, "şimdi" olması gerekiyorsa bile, bu kez 6 saat önceki gibi görmezden gelir ve davranır. Bir DateTimeörnek oluşturup saat diliminizi değiştirip kullanmaya çalıştığınızda bu durum daha da kırılır .

Farklı 'Tür' değerlerine sahip DateTime örnekleri uyumlu DEĞİLDİR.

Bazı kodlara 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 fonksiyonları otomatik olarak uyumlu zamanlara dönüşmez. TimespanNeredeyse bir saat oldu, ancak bunun yerine neredeyse 6. oldu gerekirdi "utc <artık" (Ben bile emin olmak için bir saat eklendi) gerçek olması gerekirdi, ama yine de yanlıştı.

Ayrıca Kind, aynı olmayan herhangi bir yerde evrensel zamana dönüşecek olan 'geçici çözüm' de görebilirsiniz .

Soruya doğrudan cevabım, kabul edilen cevapların her birinin ne zaman kullanılacağına dair önerisine uyuyor. G / Ç (görüntüleme ve ayrıştırma) dışında her zaman sahip nesnelerle çalışmayı denemelisiniz . Bu , nesneyi yalnızca görüntülemek için oluşturduğunuz ve hemen attığınız durumlar dışında, neredeyse her zaman kullanmanız gerektiği anlamına gelir .DateTimeKind=UtcDateTime.UtcNow


7

DateTime'ın saat dilimlerinin ne olduğu hakkında hiçbir fikri yoktur. Her zaman yerel saatinizde olduğunuzu varsayar. UtcNow sadece " Zaman dilimimi zamandan çıkart " anlamına gelir.

Saat dilimine uygun tarihleri ​​kullanmak istiyorsanız, saat / saat içeren bir tarihi / saati temsil eden DateTimeOffset öğesini kullanın . Bunu zor yoldan öğrenmek zorundaydım.


9
Tamamen hassas olmak (ve insanların performans nedenleriyle Now over UtcNow kullanmasını önlemek için), bunun tam tersi: Şimdi UtcNow'a saat dilimini ekliyor ve aslında daha yavaş bir büyüklük.
mafu

5

Sorunun "basit" yanıtı:

DateTime.Now , geçerli sistem saatini (sistemin çalıştığı saat diliminde) temsil eden bir DateTime değeri döndürür . DateTime.Kind özelliği olacak DateTimeKind.Local

DateTime.UtcNow , geçerli Evrensel Koordineli Saati (aka UTC) temsil eden ve sistemin saat dilimi ne olursa olsun aynı olacak bir DateTime değeri döndürür . DateTime.Kind özelliği olacak DateTimeKind.Utc


4

Yukarıda yapılan noktalara sadece küçük bir eklenti: DateTime yapısı da Kind adlı az bilinen bir alan içeriyor (en azından, uzun zamandır bunu bilmiyordum). Temelde zamanın yerel mi yoksa UTC mi olduğunu gösteren bir bayraktır; yerel zamanlar için UTC'den gerçek ofseti belirtmez. Davranışın hangi niyetlerle inşa edildiğini göstermesinin yanı sıra, ToUniversalTime () ve ToLocalTime () yöntemlerinin çalışma şeklini de etkiler .



1

DateTime.UtcNow sürekli, tek değerli bir zaman ölçeğidir, DateTime.Now ise sürekli veya tek değerli değildir. Birincil neden, UTC'ye uygulanmayan Yaz Saati Uygulamasıdır. UTC hiçbir zaman bir saat ileri veya geri atlamaz, oysa yerel saat (DateTime.Now). Ve geriye atladığında, aynı zaman değeri iki kez oluşur.


1

DateTime.UtcNow, Yaz Saati Uygulaması'nı atlayan Evrensel bir zaman ölçeğidir. DST nedeniyle UTC asla değişmez.

Ancak, DateTime.Şimdi DST'ye göre değiştiği için sürekli veya tek değerli değildir. Bu da DateTime.Now, aynı zaman değeri müşterileri karışık durumda bırakarak iki kez ortaya çıkabilir.


0

Uygulamanızın çalıştığı makine için yerel bir saate ihtiyacınız olduğunda (Avrupa için CEST gibi) Şimdi'yi kullanın. Evrensel bir zaman istiyorsanız - UtcNow. Sadece tercihlerinizin meselesi - muhtemelen kullanıcının saat dilimi ayarından etkilenen yerel bir web sitesi / bağımsız bir uygulama yapmak - DateTime.Now.

Bir web sitesi için sunucunun saat dilimi ayarı olduğunu unutmayın. Bu nedenle, kullanıcının saatini görüntülüyorsanız, tercih ettiği saat dilimini alın ve saati kaydırın (Utc saatini veritabanına kaydedin ve değiştirin) veya UTC'yi belirtin. Bunu yapmayı unutursanız, kullanıcı şöyle bir şey görebilir: 3 dakika önce yayınlandı ve daha sonra yakın gelecekte bir zaman :)


0

Büyük fark :) DateTime.Now SharePoint İş Akışı'nda desteklenmiyor olmasıdır DateTime.UtcNow

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.