Artikel ini menyoroti perbedaan utama antara waktu-tanggal dan datetimeoffset tipe data di SQL Server.
Kedua tipe data tersebut digunakan untuk menyimpan nilai tanggal dan waktu. Tetapi ada perbedaan yang signifikan antara keduanya.
Mungkin perbedaan yang paling jelas adalah datetimeoffset menyimpan offset zona waktu, sedangkan datetime tidak.
Perbedaan penting lainnya adalah datetimeoffset memungkinkan Anda untuk menentukan presisi (hingga 7 tempat desimal). Ini berarti datetimeoffset nilai dapat bervariasi dalam ukuran penyimpanannya, tergantung pada presisi yang digunakan.
waktu kencan type di sisi lain, memiliki ukuran dan presisi penyimpanan tetap.
Umumnya, Anda harus menghindari penggunaan datetime kecuali Anda memiliki alasan yang baik untuk menggunakannya (seperti mendukung sistem lama). Juga, datetime2 type lebih cocok daripada datetimeoffset , jadi sebaiknya Anda menggunakannya jika tidak memerlukan offset zona waktu.
Apa pun itu, inilah tabel yang membandingkan waktu-tanggal dan datetimeoffset :
Fitur | datetimeoffset | datetime |
---|---|---|
Sesuai dengan SQL (ANSI &ISO 8601) | Ya | Tidak |
Rentang Tanggal | 0001-01-01 hingga 9999-12-31 | 1753-01-01 hingga 9999-12-31 |
Rentang Waktu | 00:00:00 sampai 23:59:59.9999999 | 00:00:00 sampai 23:59:59,997 |
Panjang Karakter | Minimum 26 posisi maksimum 34 | Minimum 19 posisi maksimal 23 |
Ukuran Penyimpanan | 8 hingga 10 byte, tergantung pada presisi* * Ditambah 1 byte untuk menyimpan presisi dalam beberapa kasus. Lihat di bawah untuk info lebih lanjut. | 8 byte |
Akurasi | 100 nanodetik | Dibulatkan menjadi kelipatan .000, .003, atau .007 detik |
Presisi pecahan detik yang ditentukan pengguna | Ya | Tidak |
Rentang offset zona waktu | -14:00 sampai +14:00 | Tidak ada |
Awas dan pelestarian zona waktu | Ya | Tidak |
Mengingat musim panas | Tidak | Tidak |
Contoh 1 – Perbandingan Dasar
Bagaimanapun, berikut adalah contoh cepat untuk menunjukkan perbedaan mendasar antara datetime dan datetimeoffset .
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Hasil:
+------------------------------------+-------------------------+ | datetimeoffset | datetime | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.557 | +------------------------------------+-------------------------+
Di sini, saya menetapkan waktu tanggal variabel dengan nilai yang sama dengan datetimeoffset variabel. Hal ini menyebabkan nilai dikonversi ke datetime dan kemudian kita dapat menggunakan SELECT
pernyataan untuk melihat nilai setiap variabel.
Dalam hal ini, datetimeoffset nilai termasuk offset zona waktu dan 7 tempat desimal. waktu kencan nilai di sisi lain, tidak termasuk offset zona waktu dan hanya memiliki 3 tempat desimal. Selanjutnya, angka pecahan ketiganya dibulatkan ke atas. Ini karena akurasinya selalu dibulatkan ke peningkatan .000, .003, atau .007 detik.
Contoh 2 – Menetapkan Nilai dari Literal String
Pada contoh sebelumnya, datetime nilai ditetapkan dengan menyetelnya ke nilai yang sama dengan datetimeoffset nilai. Ketika kami melakukannya, SQL Server melakukan konversi implisit agar data "sesuai" dengan tipe data baru.
Jika kami mencoba menetapkan nilai yang sama langsung ke datetime variabel kita mendapatkan kesalahan:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = '2025-05-21 10:15:30.5555555 +07:30'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Hasil:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Ini karena waktu tanggal tipe data tidak mendukung literal string dengan offset zona waktu. Selain itu, ini tidak mendukung literal string dengan lebih dari 3 tempat desimal.
Jadi, jika kita menghapus offset zona waktu, tetapi menyimpan semua pecahan detik, kita masih akan mendapatkan error:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = '2025-05-21 10:15:30.5555555'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Hasil:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Untuk membuatnya berfungsi, kita perlu menetapkan nilai dengan tidak lebih dari 3 tempat desimal:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = '2025-05-21 10:15:30.555'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Hasil:
+------------------------------------+-------------------------+ | datetimeoffset | datetime | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.557 | +------------------------------------+-------------------------+
Apa pun itu, waktu kencan akan selalu memiliki nilai yang berbeda dengan datetimeoffset , karena tidak menyertakan offset zona waktu. Ini akan benar bahkan jika kita menggunakan presisi pecahan detik dan nilai pecahan detik yang sama.
Untuk menunjukkannya, inilah yang terjadi jika kita menetapkan nilai yang sama ke datetimeoffset :
DECLARE @thedatetimeoffset datetimeoffset(3), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.123'; SET @thedatetime = '2025-05-21 10:15:30.123'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Hasil:
+------------------------------------+-------------------------+ | datetimeoffset | datetime | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.1230000 +00:00 | 2025-05-21 10:15:30.123 | +------------------------------------+-------------------------+
Dalam hal ini datetimeoffset menggunakan skala 3, yang memberikannya 3 tempat desimal (sama dengan datetime ). Ini dilakukan dengan menggunakan datetimeoffset(3) saat mendeklarasikan variabel.
Saya juga mengubah pecahan detik sehingga datetime tidak akan membulatkannya (sehingga kedua nilai memiliki bagian pecahan yang sama persis).
Apapun, datetimeoffset masih menambahkan offset zona waktu, setel ke nilai default +00:00.
Perhatikan bahwa sistem saya menampilkan angka nol di datetimeoffset bagian pecahan, tetapi nilainya hanya menggunakan 3 tempat desimal.
Contoh 3 – Ukuran Penyimpanan
waktu kencan tipe data menggunakan 8 byte.
offset datetime tipe data menggunakan 8, 9, atau 10 byte, tergantung pada presisinya.
Oleh karena itu, Anda tidak menghemat ukuran penyimpanan apa pun dengan menggunakan datetime .
Namun, jika Anda mengonversi datetimeoffset nilai ke konstanta biner, itu menambahkan 1 byte untuk menyimpan presisi.
Inilah yang terjadi jika kita menggunakan DATALENGTH()
fungsi untuk mengembalikan jumlah byte yang digunakan untuk setiap nilai kita:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = @thedatetimeoffset; SELECT DATALENGTH(@thedatetimeoffset) AS 'datetimeoffset', DATALENGTH(@thedatetime) AS 'datetime';
Hasil
+------------------+------------+ | datetimeoffset | datetime | |------------------+------------| | 10 | 8 | +------------------+------------+
Seperti yang diharapkan, 10 byte untuk datetimeoffset dan 8 byte untuk datetime .
Tetapi jika kita mengonversinya menjadi varbinary , kita mendapatkan yang berikut:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = @thedatetimeoffset; SELECT DATALENGTH(CAST(@thedatetimeoffset AS varbinary(16))) AS 'datetimeoffset', DATALENGTH(CAST(@thedatetime AS varbinary(16))) AS 'datetime';
Hasil
+------------------+------------+ | datetimeoffset | datetime | |------------------+------------| | 11 | 8 | +------------------+------------+
Satu byte tambahan ditambahkan ke datetimeoffset nilai tetapi tidak ke datetime nilai. Ini karena datetimeoffset value membutuhkan byte tambahan untuk menyimpan presisi (karena presisi ditentukan pengguna). waktu kencan nilai di sisi lain memiliki presisi tetap, jadi presisi tidak perlu disimpan dengan nilai.
Banyak pengembang berasumsi bahwa mengonversi ke varbinary mewakili bagaimana SQL Server benar-benar menyimpan nilai tanggal dan waktu. Namun ini hanya sebagian benar.
Meskipun benar bahwa SQL Server menyimpan nilai tanggal dan waktunya dalam heksadesimal, nilai heksadesimal tersebut sebenarnya tidak menyertakan presisi saat menyimpan datetimeoffset nilai-nilai. Ini karena presisi termasuk dalam definisi kolom.
Untuk detail lebih lanjut tentang bagaimana tipe data ini disimpan dalam database, lihat Memahami Ukuran Penyimpanan 'datetimeoffset' di SQL Server.
Haruskah saya menggunakan 'datetime' atau 'datetimeoffset'?
Jika Anda perlu menyertakan offset zona waktu, maka Anda harus menggunakan datetimeoffset . Jika tidak, maka datetime mungkin cukup.
Namun, Microsoft menyarankan Anda menggunakan datetime2 untuk pekerjaan baru, karena memiliki banyak manfaat dibandingkan datetime .
Lihat datetime vs datetime2 untuk perbandingan tipe data ini.