it-swarm-id.com

DateTime.Now vs. DateTime.UtcNow

Saya sudah bertanya-tanya apa sebenarnya prinsip-prinsip bagaimana kedua properti itu bekerja. Saya tahu yang kedua bersifat universal dan pada dasarnya tidak berurusan dengan zona waktu, tetapi bisakah seseorang menjelaskan secara rinci bagaimana mereka bekerja dan mana yang harus digunakan dalam skenario apa?

197
Slavo

DateTime.UtcNow memberi tahu Anda tanggal dan waktu seperti di Waktu Universal Terkoordinasi, yang juga disebut zona waktu Waktu Rata-Rata Greenwich - pada dasarnya seperti jika Anda berada di London Inggris, tetapi tidak selama musim panas. DateTime.Now memberikan tanggal dan waktu seperti yang akan muncul kepada seseorang di lokal Anda saat ini.

Saya akan merekomendasikan menggunakan DateTime.Now setiap kali Anda menampilkan tanggal untuk seorang manusia - dengan cara itu mereka merasa nyaman dengan nilai yang mereka lihat - itu adalah sesuatu yang mereka dapat dengan mudah dibandingkan dengan apa yang mereka lihat di jam tangan atau jam mereka . Gunakan DateTime.UtcNow ketika Anda ingin menyimpan tanggal atau menggunakannya untuk perhitungan nanti seperti itu (dalam model client-server) perhitungan Anda tidak menjadi bingung oleh klien di zona waktu yang berbeda dari server Anda atau dari satu sama lain.

311
Blair Conrad

Ini benar-benar sangat sederhana, jadi saya pikir itu tergantung pada audiens Anda dan di mana mereka tinggal.

Jika Anda tidak menggunakan Utc, Anda harus tahu zona waktu orang yang Anda tunjukkan tanggal dan waktu - jika tidak, Anda akan memberi tahu mereka sesuatu terjadi pada 3 PM di waktu sistem atau server, ketika itu benar-benar terjadi pada 5 PM tempat mereka tinggal.

Kami menggunakan DateTime.UtcNow karena kami memiliki pemirsa web global, dan karena saya lebih suka untuk tidak mengomel setiap pengguna untuk mengisi formulir yang menunjukkan zona waktu mereka tinggal.

Kami juga menampilkan waktu relatif (2 jam yang lalu, 1 hari yang lalu, dll) sampai pos cukup umur sehingga waktunya "sama" di mana pun di Bumi Anda tinggal.

80
Jeff Atwood

Perhatikan juga perbedaan kinerja; DateTime.UtcNow adalah sekitar 30 kali lebih cepat daripada DateTime.Now, karena DateTime secara internal. Sekarang melakukan banyak penyesuaian zona waktu (Anda dapat dengan mudah memverifikasi ini dengan Reflektor).

Jadi jangan gunakan DateTime. Sekarang untuk pengukuran waktu relatif.

29
Magnus Krisell

Satu konsep utama untuk dipahami dalam .NET adalah bahwa sekarang adalah sekarang semua di atas bumi tidak peduli apa zona waktu Anda. Jadi jika Anda memuat variabel dengan DateTime.Now atau DateTime.UtcNow - penugasannya identik. * Objek DateTime Anda tahu zona waktu tempat Anda berada dan mengambilnya ke akun terlepas dari tugasnya.

Kegunaan DateTime.UtcNow sangat berguna saat menghitung tanggal melintasi batas Waktu Daylight Savings Time. Artinya, di tempat-tempat yang berpartisipasi dalam penghematan waktu siang hari, kadang-kadang ada 25 jam dari siang hingga siang hari berikutnya, dan kadang-kadang ada 23 jam antara siang dan siang hari berikutnya. Jika Anda ingin menentukan dengan benar jumlah jam dari waktu A dan waktu B, Anda harus terlebih dahulu menerjemahkan masing-masing ke setara UTC mereka sebelum menghitung TimeSpan.

Ini dicakup oleh posting blog yang saya tulis yang menjelaskan lebih lanjut TimeSpan, dan termasuk tautan ke artikel MS yang bahkan lebih luas tentang topik tersebut.

* Klarifikasi: Tugas mana pun akan menyimpan waktu saat ini. Jika Anda memuat dua variabel, satu melalui DateTime.Now() dan lainnya melalui DateTime.UtcNow(), perbedaan TimeSpan antara keduanya akan menjadi milidetik, bukan jam dengan asumsi Anda berada dalam zona waktu beberapa jam dari GMT. Seperti disebutkan di bawah, mencetak nilai String mereka akan menampilkan string yang berbeda.

26
Carl Camera

Ini pertanyaan yang bagus. Saya menghidupkannya kembali untuk memberikan sedikit detail tentang bagaimana .Net berperilaku dengan nilai Kind yang berbeda. Seperti yang ditunjukkan oleh @Jan Zich, Ini sebenarnya properti yang sangat penting dan diatur secara berbeda tergantung pada apakah Anda menggunakan Now atau UtcNow.

Secara internal tanggal disimpan sebagai Ticks yang (bertentangan dengan jawaban @Carl Camera) berbeda tergantung pada apakah Anda menggunakan Now atau UtcNow.

DateTime.UtcNow berperilaku seperti bahasa lain. Ini menetapkan Ticks ke nilai berdasarkan GMT. Ini juga menetapkan Kind menjadi Utc.

DateTime.Now mengubah nilai Ticks menjadi apa jadinya jika itu adalah waktu Anda di zona waktu GMT. Ini juga menetapkan Kind menjadi Local.

Jika Anda 6 jam di belakang (GMT-6), Anda akan mendapatkan waktu GMT dari 6 jam yang lalu. .Net sebenarnya mengabaikan Kind dan memperlakukan kali ini seolah-olah itu 6 jam yang lalu, meskipun itu seharusnya "sekarang". Ini bahkan akan semakin terputus jika Anda membuat instance DateTime lalu ubah zona waktu Anda dan cobalah untuk menggunakannya.

instance DateTime dengan nilai 'Jenis' yang berbeda TIDAK kompatibel.

Mari kita lihat beberapa kode ...

    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

Seperti yang Anda lihat di sini, perbandingan dan fungsi matematika tidak secara otomatis dikonversi ke waktu yang kompatibel. Timespan seharusnya hampir satu jam, tetapi sebaliknya hampir 6. "utc <now" seharusnya benar (saya bahkan menambahkan satu jam untuk memastikan), tetapi masih salah.

Anda juga dapat melihat 'bekerja di sekitar' yang hanya mengkonversi ke waktu universal di mana saja yang Kind tidak sama.

Jawaban langsung saya untuk pertanyaan tersebut setuju dengan rekomendasi jawaban yang diterima tentang kapan harus menggunakan masing-masing. Anda harus selalu coba untuk bekerja dengan objek DateTime yang memiliki Kind=Utc, kecuali selama i/o (displaying dan parsing). Ini berarti Anda hampir selalu menggunakan DateTime.UtcNow, kecuali untuk kasus-kasus di mana Anda membuat objek hanya untuk menampilkannya, dan segera membuangnya.

15
Ted Bigham

DateTime tidak tahu apa zona waktu itu. Itu selalu mengasumsikan Anda berada di waktu setempat. UtcNow hanya berarti "Kurangi zona waktu saya dari waktu".

Jika Anda ingin menggunakan tanggal yang diketahui oleh zona waktu, gunakan DateTimeOffset, yang mewakili tanggal/waktu dengan zona waktu. Saya harus belajar itu dengan cara yang sulit.

6
Omer van Kloeten

Jawaban "sederhana" untuk pertanyaan ini adalah:

DateTime.Now mengembalikan nilai DateTime yang mewakili waktu sistem saat ini (dalam zona waktu apa pun yang digunakan sistem). Properti DateTime.Kind akan menjadi DateTimeKind.Local

DateTime.UtcNow mengembalikan nilai DateTime yang mewakili Waktu Universal Terkoordinasi saat ini (alias UTC) yang akan sama terlepas dari zona waktu sistem. Properti DateTime.Kind akan menjadi DateTimeKind.Utc

4
PapillonUK

Hanya sedikit tambahan pada poin yang dibuat di atas: struct DateTime juga mengandung sedikit bidang yang dikenal --- Jenis (setidaknya, saya tidak tahu tentang itu untuk waktu yang lama). Ini pada dasarnya hanya sebuah bendera yang menunjukkan apakah waktu bersifat lokal atau UTC; itu tidak menentukan offset nyata dari UTC untuk waktu lokal. Selain fakta bahwa itu menunjukkan dengan niat apa stuct dibangun, itu juga mempengaruhi cara metode ToUniversalTime () dan ToLocalTime () bekerja.

4
Jan Zich
2
Sorin Comanescu

DateTime.UtcNow adalah skala waktu bernilai tunggal yang berkelanjutan, sedangkan DateTime.Now tidak berkelanjutan atau bernilai tunggal. Alasan utamanya adalah Daylight Savings Time, yang tidak berlaku untuk UTC. Jadi UTC tidak pernah melompat maju atau mundur satu jam, sedangkan waktu setempat (DateTime.Now) tidak. Dan ketika melompat mundur, nilai waktu yang sama terjadi dua kali.

1
user1315023

DateTime.UtcNow adalah skala waktu Universal menghilangkan Daylight Savings Time. Jadi UTC tidak pernah berubah karena DST.

Tapi, DateTime. Sekarang tidak kontinu atau bernilai tunggal karena berubah menurut DST. Yang berarti DateTime. Sekarang, nilai waktu yang sama dapat terjadi dua kali meninggalkan pelanggan dalam keadaan bingung.

1
ChaiVan

Saat Anda membutuhkan waktu lokal untuk mesin yang menjalankan aplikasi Anda (seperti CEST untuk Eropa), gunakan Sekarang. Jika Anda ingin waktu universal - UtcNow. Ini hanya masalah preferensi Anda - mungkin membuat situs web lokal/aplikasi mandiri yang Anda ingin menggunakan waktu yang dimiliki pengguna - sangat terpengaruh oleh pengaturan zona waktunya - DateTime.Now.

Hanya ingat, untuk situs web itu adalah pengaturan zona waktu server. Jadi, jika Anda menampilkan waktu untuk pengguna, dapatkan zona waktu pilihannya dan ubah waktunya (cukup simpan waktu Utc ke basis data, dan modifikasikan) atau tentukan UTC. Jika Anda lupa melakukannya, pengguna dapat melihat sesuatu seperti: diposting 3 minus lal dan kemudian di masa mendatang dekat itu :)

0
kender