DateTimeOffset
adalah representasi waktu sesaat (juga dikenal sebagai waktu absolut ). Maksud saya adalah momen dalam waktu yang bersifat universal untuk semua orang (tidak memperhitungkan detik kabisat , atau efek relativistik dari pelebaran waktu ). Cara lain untuk mewakili waktu sesaat adalah dengan DateTime
mana .Kind
adalah DateTimeKind.Utc
.
Ini berbeda dari waktu kalender (juga dikenal sebagai waktu sipil ), yang merupakan posisi pada kalender seseorang, dan ada banyak kalender berbeda di seluruh dunia. Kami menyebut zona waktu kalender ini . Waktu kalender diwakili oleh DateTime
mana .Kind
adalah DateTimeKind.Unspecified
, atau DateTimeKind.Local
. Dan .Local
hanya bermakna dalam skenario di mana Anda memiliki pemahaman tersirat di mana komputer yang menggunakan hasil diposisikan. (Misalnya, stasiun kerja pengguna)
Jadi, mengapa DateTimeOffset
bukan UTC DateTime
? Ini semua tentang perspektif. Mari kita gunakan analogi - kita akan berpura-pura menjadi fotografer.
Bayangkan Anda berdiri di garis waktu kalender, mengarahkan kamera ke seseorang di garis waktu sesaat yang diletakkan di depan Anda. Anda mengatur kamera berdasarkan aturan zona waktu Anda - yang berubah secara berkala karena waktu musim panas, atau karena perubahan lain pada definisi hukum zona waktu Anda. (Anda tidak memiliki tangan yang mantap, jadi kamera Anda goyah.)
Orang yang berdiri di foto akan melihat dari sudut mana kamera Anda berasal. Jika orang lain mengambil foto, mereka bisa dari sudut yang berbeda. Inilah yang diwakili oleh Offset
bagian itu DateTimeOffset
.
Jadi jika Anda memberi label pada kamera "Waktu Timur", terkadang Anda menunjuk dari -5, dan kadang-kadang Anda menunjuk dari -4. Ada kamera di seluruh dunia, semuanya berlabel hal yang berbeda, dan semua menunjuk pada garis waktu instan yang sama dari sudut yang berbeda. Beberapa dari mereka tepat di sebelah (atau di atas) satu sama lain, jadi hanya mengetahui offset tidak cukup untuk menentukan zona waktu yang terkait dengan waktu.
Dan bagaimana dengan UTC? Nah, itu satu-satunya kamera di luar sana yang dijamin memiliki tangan mantap. Ada di atas tripod, dengan kuat berlabuh ke tanah. Itu tidak ke mana-mana. Kami menyebut sudut pandangnya sebagai titik nol.
Jadi - apa yang dikatakan analogi ini kepada kita? Ini memberikan beberapa panduan intuitif-
Jika Anda merepresentasikan waktu relatif terhadap tempat tertentu, wakili waktu kalender dengan a DateTime
. Pastikan Anda tidak pernah mengacaukan satu kalender dengan yang lain. Unspecified
harus menjadi asumsi Anda. Local
hanya bermanfaat dari DateTime.Now
. Sebagai contoh, saya mungkin mendapatkan DateTime.Now
dan menyimpannya dalam database - tetapi ketika saya mengambilnya, saya harus berasumsi bahwa itu adalah database Unspecified
. Saya tidak dapat mengandalkan bahwa kalender lokal saya adalah kalender yang sama dengan aslinya.
Jika Anda harus selalu yakin akan momen tersebut, pastikan Anda mewakili waktu instan. Gunakan DateTimeOffset
untuk menegakkannya, atau menggunakan UTC DateTime
dengan konvensi.
Jika Anda perlu melacak waktu sesaat, tetapi Anda juga ingin tahu "Jam berapa pengguna pikir itu ada di kalender lokal mereka?" - maka Anda harus menggunakan a DateTimeOffset
. Ini sangat penting untuk sistem ketepatan waktu, misalnya - baik untuk masalah teknis dan hukum.
Jika Anda perlu memodifikasi rekaman sebelumnya DateTimeOffset
- Anda tidak memiliki informasi yang cukup di offset saja untuk memastikan bahwa offset baru masih relevan bagi pengguna. Anda juga harus menyimpan pengenal zona waktu (pikirkan - Saya perlu nama kamera itu sehingga saya dapat mengambil gambar baru meskipun posisinya telah berubah).
Juga harus ditunjukkan bahwa Noda Time memiliki representasi yang disebut ZonedDateTime
untuk ini, sedangkan perpustakaan kelas .Net tidak memiliki hal yang serupa. Anda harus menyimpan nilai DateTimeOffset
dan TimeZoneInfo.Id
nilai.
Kadang-kadang, Anda ingin mewakili waktu kalender yang bersifat lokal untuk "siapa pun yang melihatnya". Misalnya, ketika mendefinisikan apa artinya hari ini . Hari ini selalu tengah malam hingga tengah malam, tetapi ini mewakili jumlah tumpang tindih yang hampir tak terbatas pada garis waktu sesaat. (Dalam praktiknya kami memiliki sejumlah zona waktu yang terbatas, tetapi Anda dapat mengimbangi hingga tanda centang). Jadi dalam situasi ini, pastikan Anda memahami cara membatasi "siapa yang bertanya?" pertanyaan ke zona waktu tunggal, atau berurusan dengan menerjemahkannya kembali ke waktu sesaat yang sesuai.
Berikut adalah beberapa bagian lain tentang hal DateTimeOffset
itu yang mendukung analogi ini, dan beberapa tips untuk menjaganya agar tetap lurus:
Jika Anda membandingkan dua DateTimeOffset
nilai, mereka pertama dinormalisasi ke nol offset sebelum membandingkan. Dengan kata lain, 2012-01-01T00:00:00+00:00
dan 2012-01-01T02:00:00+02:00
merujuk pada momen instan yang sama, dan karenanya setara.
Jika Anda melakukan setiap pengujian unit dan kebutuhan untuk menjadi tertentu dari offset, tes kedua yang DateTimeOffset
nilai, dan .Offset
properti secara terpisah.
Ada konversi implisit satu arah yang dibangun ke dalam kerangka .Net yang memungkinkan Anda mengirimkan a DateTime
ke DateTimeOffset
parameter atau variabel apa pun . Ketika melakukannya, yang .Kind
penting . Jika Anda melewati jenis UTC, itu akan dibawa dengan nol offset, tetapi jika Anda melewati salah satu .Local
atau .Unspecified
, itu akan dianggap sebagai lokal . Kerangka kerja ini pada dasarnya mengatakan, "Ya, Anda meminta saya untuk mengubah waktu kalender menjadi waktu instan, tetapi saya tidak tahu dari mana ini berasal, jadi saya hanya akan menggunakan kalender lokal." Ini adalah masalah besar jika Anda memuat yang tidak ditentukan DateTime
pada komputer dengan zona waktu yang berbeda. (IMHO - yang seharusnya melempar pengecualian - tetapi tidak.)
Plug tak tahu malu:
Banyak orang telah berbagi dengan saya bahwa mereka menganggap analogi ini sangat berharga, jadi saya memasukkannya ke dalam kursus Pluralsight saya, Fundamental Date and Time . Anda akan menemukan langkah demi langkah langkah-langkah analogi kamera dalam modul kedua, "Konteks Konteks", dalam klip berjudul "Waktu Kalender vs. Waktu Instan".