Menyimpan DateTime (UTC) vs. menyimpan DateTimeOffset

95

Saya biasanya memiliki "interseptor" yang sebelum membaca / menulis dari / ke database melakukan konversi DateTime (dari UTC ke waktu lokal, dan dari waktu lokal ke UTC), jadi saya dapat menggunakan DateTime.Now(derivasi dan perbandingan) di seluruh sistem tanpa khawatir tentang zona waktu.

Mengenai serialisasi dan pemindahan data antar komputer, tidak perlu repot, karena datetime selalu UTC.

Haruskah saya terus menyimpan tanggal saya (SQL 2008 - datetime) dalam format UTC atau haruskah saya menyimpannya menggunakan DateTimeOffset(SQL 2008 - datetimeoffset)?

Tanggal UTC di database (tipe datetime) telah bekerja dan dikenal begitu lama, mengapa mengubahnya? Apa kelebihannya?

Saya telah melihat artikel seperti ini , tetapi saya tidak 100% yakin. Ada pemikiran?

Frederico
sumber
Pertanyaan terkait: stackoverflow.com/questions/2532729/…
Oded
1
Lihat juga: DateTime vs DateTimeOffset - ditulis untuk .Net, tetapi secara konseptual juga berlaku untuk SQL.
Matt Johnson-Pint

Jawaban:

131

Ada satu perbedaan besar, di mana Anda tidak dapat menggunakan UTC sendirian.

  • Jika Anda memiliki skenario seperti ini

    • Satu server dan beberapa klien (semua secara geografis dalam zona waktu yang berbeda )
    • Klien membuat beberapa data dengan informasi datetime
    • Klien menyimpan semuanya di server pusat
  • Kemudian:

    • datetimeoffset menyimpan waktu lokal klien dan JUGA offset ke waktu UTC
    • semua klien mengetahui waktu UTC untuk semua data dan juga waktu lokal di tempat asal informasi tersebut
  • Tapi:

    • UTC datetime menyimpan hanya waktu UTC , jadi Anda tidak memiliki informasi tentang waktu lokal di lokasi klien tempat data berasal
    • Klien lain tidak mengetahui waktu lokal tempat itu, dari mana informasi datetime berasal
    • Klien lain hanya dapat menghitung waktu lokal mereka dari database (menggunakan waktu UTC) bukan waktu lokal klien, tempat asal data

Contoh sederhananya adalah sistem reservasi tiket pesawat ... Tiket penerbangan harus berisi 2 kali: - waktu "lepas landas" (dalam zona waktu "Dari" kota) - waktu "mendarat" (dalam zona waktu kota "Tujuan")

Marcel Toth
sumber
2
Ini adalah penjelasan terbaik yang pernah saya baca tentang kapan waktu yang tepat, dan saya telah banyak membaca. Bagi kami, dari sini, tampaknya tidak begitu. Kami mendapatkan waktu dalam UTC untuk data eksternal kami, dan kami mengetahui lokasi dari sumber lain jika diperlukan (dan belum pernah). Terima kasih telah membuatnya tampak begitu jelas.
Andrew Backer
19
Anda mengatakan "datetimeoffset menyimpan waktu UTC dan JUGA mengimbangi ke waktu lokal klien", tetapi waktu offset menyimpan waktu LOKAL + Offset, atau waktu UTC + offset sama dengan +0.
Serhii Kyslyi
meskipun Anda bisa saja mentransmisikan DTO ke DT karena basis DT adalah UTC (meskipun ini akan menjadi langkah tambahan untuk semua orang yang menggunakan database, dan bisa dibilang tidak lebih sederhana daripada hanya menggunakan waktu UTC saja)
iliketocode
2
Sepertinya DateTmeOffset menyimpan "Waktu Lokal dan UTC Offset", bukan "Waktu UTC dan Offset UTC". Jika Anda mentransmisikan ke datetime atau menggunakan salah satu fungsi datepart, Anda mendapatkan komponen tanggal dan waktu lokal.
Triynko
" Semua klien mengetahui waktu UTC dari semua data dan juga waktu lokal di tempat asal informasi" Meskipun menyimpan sebagai bagian dari bidang tanggal terasa tidak normal dalam kasus itu. Apa kasus penggunaannya - yaitu, mengapa Anda tidak menggunakan UTC & menarik offset ke InputLocationId(atau entitas normal serupa). Akan ada perhitungan yang terlibat (halo, pengecualian ... terutama Anda, Indiana ), tetapi ini masih merupakan proses deterministik - dan keseimbangan logika waktu aplikasi sangat mudah.
ruffin
23

Anda sepenuhnya benar menggunakan UTC untuk semua waktu historis (yaitu peristiwa pencatatan terjadi). Selalu mungkin untuk beralih dari UTC ke waktu lokal tetapi tidak selalu sebaliknya.

Kapan menggunakan waktu setempat? Jawab pertanyaan ini:

Jika pemerintah tiba-tiba memutuskan untuk mengubah penghematan siang hari, apakah Anda ingin data ini berubah dengannya?

Simpan waktu setempat hanya jika jawabannya "ya". Jelas itu hanya untuk tanggal yang akan datang, dan biasanya hanya untuk tanggal yang mempengaruhi orang dalam beberapa cara.

Mengapa menyimpan zona waktu / offset?

Pertama, jika Anda ingin mencatat apa offset untuk pengguna yang melakukan tindakan, Anda mungkin lebih baik melakukannya, yaitu saat login, catat lokasi dan zona waktu untuk pengguna tersebut.

Kedua, jika Anda ingin mengubah tampilan, Anda harus memiliki tabel semua transisi offset waktu lokal untuk zona waktu tersebut, cukup mengetahui offset saat ini tidak cukup, karena jika Anda menampilkan tanggal / waktu dari enam bulan yang lalu offset akan berbeda.

Ben
sumber
4
Windows UTC ke konversi waktu lokal memperhitungkan saat waktu musim panas berubah untuk tanggal historis. Saya tidak mengerti mengapa Anda ingin menyimpan waktu lokal dalam kasus itu.
Jamiegs
1
@Jamiegs Windows hanya secara historis mengetahui "informasi historis terakhir" (seperti yang diisyaratkan / dicatat dalam dokumentasi DateTime .NET). Itu tidak komprehensif.
2
tentu saja, Anda juga harus menyimpan lokasi acara, jika tidak, Anda tidak dapat mengatakan pada "waktu setempat" acara tersebut terjadi.
keuleJ
20

DATETIMEOFFSET memberi Anda kemampuan untuk menyimpan waktu lokal dan waktu UTC dalam satu bidang.

Hal ini memungkinkan pelaporan yang sangat sederhana dan efisien dalam waktu lokal atau UTC tanpa perlu memproses data untuk ditampilkan dengan cara apa pun.

Ini adalah dua persyaratan paling umum - waktu lokal untuk laporan lokal dan waktu UTC untuk laporan grup.

Waktu lokal disimpan di bagian DATETIME dari DATETIMEOFFSET dan OFFSET dari UTC disimpan di bagian OFFSET, sehingga konversinya sederhana dan, karena tidak memerlukan pengetahuan tentang zona waktu asal data, semua dapat dilakukan di tingkat database .

Jika Anda tidak memerlukan waktu turun ke milidetik, misalnya hanya untuk menit atau detik, Anda dapat menggunakan DATETIMEOFFSET (0). Bidang DATETIMEOFFSET kemudian hanya akan membutuhkan penyimpanan 8 byte - sama dengan DATETIME.

Oleh karena itu, menggunakan DATETIMEOFFSET daripada UTC DATETIME memberikan lebih banyak fleksibilitas, efisiensi, dan kesederhanaan untuk pelaporan.

PapillonUK
sumber
Framework entitas yang terlalu buruk tidak memiliki cara apa pun untuk mengakses datetime lokal dari bidang datetimeoffset, sehingga tidak mungkin untuk membuat kueri untuk tanggal lokal tertentu.
Triynko
@ Triynko dapatkah Anda menjelaskan apa yang Anda maksud? Contoh?
reidLinden