it-swarm.asia

Bagaimana cara menangani TimeZone dengan benar di SQL Server?

Server pengembangan lokal saya di Timur Tengah, tetapi server produksi saya di Inggris.

Saya perlu menunjukkan tanggal kepada pengguna di zona waktu mereka. Misalnya, jika pengguna di Arab Saudi maka saya harus menunjukkan waktu sesuai dengan format Arab Saudi.

Haruskah saya membuat tabel database baru yang disebut TimeZone dan menghemat waktu dalam UTC?

39
user960567

Sayangnya, tidak ada perbaikan cepat untuk ini. Internasionalisasi suatu aplikasi harus menjadi bagian dari diskusi desain pertama, karena ia benar-benar menjadi inti dari banyak bidang yang berbeda, termasuk perbandingan tanggal/waktu dan pemformatan keluaran.

Bagaimanapun, untuk mendapatkan jejak Doing It Right, penting untuk menyimpan informasi zona waktu dengan waktu. Dengan kata lain, menyadari bahwa tanggal/waktu 20130407 14:50 is tidak berarti tanpa salah (a) termasuk offset UTC zona waktu saat itu(catatan 1), atau (b) memastikan bahwa semua logika yang memasukkan nilai-nilai ini pertama kali dikonversi ke offset tetap tertentu (kemungkinan besar 0). Tanpa salah satu dari hal-hal itu, dua nilai waktu yang diberikan adalah tak tertandingi, dan datanya rusak. (Metode terakhir bermain dengan api(catatan 2), ngomong-ngomong; jangan lakukan itu.)

Di SQL Server 2008+, Anda dapat menyimpan offset dengan waktu secara langsung dengan menggunakan datetimeoffset tipe data. (Untuk kelengkapan, pada tahun 2005 dan sebelumnya, saya akan menambahkan kolom kedua untuk menyimpan nilai offset UTC saat itu (dalam menit).)

Ini memudahkan aplikasi jenis desktop, karena platform ini biasanya memiliki mekanisme untuk secara otomatis mengkonversi zona tanggal/waktu + waktu ke waktu lokal dan kemudian memformat untuk output, semua berdasarkan pada pengaturan regional pengguna.

Untuk web, yang merupakan arsitektur yang terputus secara inheren, bahkan dengan data back-end diatur dengan benar, itu lebih kompleks karena Anda memerlukan informasi tentang klien untuk dapat melakukan konversi dan/atau pemformatan. Ini biasanya dilakukan melalui pengaturan preferensi pengguna (aplikasi mengkonversi/memformat hal-hal sebelum output), atau hanya menunjukkan hal-hal dengan format tetap dan offset zona waktu yang sama untuk semua orang (yang dilakukan oleh platform Stack Exchange saat ini).

Anda dapat melihat bagaimana jika data back-end tidak diatur dengan benar, sangat cepat itu akan menjadi rumit dan meretas. Saya tidak akan merekomendasikan salah satu dari jalan-jalan tersebut karena Anda hanya akan berakhir dengan lebih banyak masalah di telepon.

Catatan 1:

Offset UTC zona waktu tidak tetap: pertimbangkan penghematan siang hari di mana offset UTC zona bervariasi dengan plus atau minus satu jam. Juga tanggal penghematan siang hari zona bervariasi secara teratur. Jadi menggunakan datetimeoffset (atau gabungan dari local time dan UTC offset at that time) menghasilkan pemulihan informasi maksimum.

Catatan 2:

Ini tentang mengendalikan input data. Meskipun tidak ada cara yang mudah untuk memvalidasi nilai yang masuk, lebih baik untuk menegakkan standar sederhana yang tidak melibatkan perhitungan. Jika API publik mengharapkan tipe data yang menyertakan offset, persyaratan itu akan jelas bagi pemanggil.

Jika bukan itu masalahnya, penelepon harus bergantung pada dokumentasi (jika mereka membacanya), atau perhitungannya dilakukan secara tidak benar, dll. Ada lebih sedikit mode kegagalan/bug saat memerlukan offset, khususnya untuk sistem terdistribusi ( atau bahkan hanya web/database pada server terpisah seperti yang terjadi di sini).

Menyimpan offset tetap membunuh dua burung dengan satu batu; dan bahkan jika itu tidak diperlukan sekarang, itu membuat kemungkinan tersedia nanti jika perlu. Benar itu membutuhkan lebih banyak penyimpanan, tapi saya pikir itu layak trade-off karena data hilang jika tidak pernah direkam.

51
Jon Seigel

Saya telah mengembangkan solusi komprehensif untuk konversi zona waktu di SQL Server. Lihat Dukungan Zona Waktu SQL Server di GitHub .

Itu benar menangani konversi antara zona waktu, dan ke dan dari UTC, termasuk waktu musim panas.

Konsepnya mirip dengan solusi "T-SQL Toolbox" yang dijelaskan dalam jawaban iklan, tetapi menggunakan zona waktu IANA/Olson/TZDB yang lebih umum daripada Microsoft, dan itu mencakup utilitas untuk menjaga data tetap dipertahankan sebagai rilis baru dari TZDB keluar.

Contoh penggunaan (untuk menjawab OP):

SELECT Tzdb.UtcToLocal(sysutcdatetime(), 'Asia/Riyadh') as CurrentTimeInSaudiArabia

Lihat readme on GitHub untuk API tambahan dan penjelasan terperinci.

Juga, perhatikan bahwa karena ini adalah solusi berbasis UDF, itu tidak dirancang dengan kinerja sebagai tujuan utama. Masih akan lebih baik jika fungsi ini dibangun ke SQL Server, sama seperti bagaimana CONVERT_TZ fungsi ada di Oracle dan MySQL.

15

Saya telah mengembangkan dan menerbitkan proyek "T-SQL Toolbox" pada codeplex untuk membantu siapa saja yang berjuang dengan penanganan waktu dan zona waktu di SQL Server. Ini open source dan sepenuhnya gratis untuk digunakan.

Ini menawarkan UDFs konversi datetime mudah menggunakan T-SQL biasa dengan tabel konfigurasi tambahan di luar kotak.

Dalam contoh Anda, Anda dapat menggunakan sampel berikut:

SELECT [DateTimeUtil].[UDF_ConvertLocalToLocalByTimezoneIdentifier] (
    'GMT Standard Time', -- the original timezone in which your datetime is stored
    'Middle East Standard Time', -- the target timezone for your user
    '2014-03-30 01:55:00' -- the original datetime you want to convert
)

Ini akan mengembalikan nilai datetime yang dikonversi untuk pengguna Anda.

Daftar semua zona waktu yang didukung dapat ditemukan dalam tabel "DateTimeUtil.Timezone" juga disediakan dalam database T-SQL Toolbox.

7
adss

SQL Server membuat modifikasi pada 2005 dan seterusnya di mana zona waktu internal disimpan dalam UTC. Ini sebagian besar disebabkan oleh replikasi-geo dan proyektor HA yang melibatkan pengiriman log, dan menghemat waktu pengiriman log di zona waktu yang berbeda membuat metode lama tidak dapat mengembalikannya.

Dengan demikian, menyimpan segala sesuatu secara internal dalam waktu UTC memungkinkan SQL Server berfungsi dengan baik secara global. Ini adalah salah satu alasan mengapa penghematan siang hari adalah jenis yang menyusahkan untuk ditangani di Windows, karena produk MS lainnya seperti Outlook juga menyimpan tanggal/waktu secara internal sebagai UTC dan membuat offset yang perlu ditambal.

Saya bekerja di sebuah perusahaan di mana kami memiliki ribuan server (bukan Server MS SQL, tetapi semua jenis server) tersebar di seluruh dunia, dan jika kami tidak secara spesifik memaksa segalanya untuk pergi dengan UTC, kami semua akan menjadi gila sangat cepat.

6
Ali Razeghi

Saya mungkin kehilangan sesuatu yang jelas, tetapi jika semua yang ingin Anda lakukan adalah menampilkan tanggal menggunakan zona waktu pengguna dan format bahasa, cara paling sederhana adalah dengan selalu menyimpan tanggal dalam UTC dalam database dan membiarkan aplikasi klien mengkonversi dari UTC ke lokal zona waktu dan gunakan pengaturan regional pengguna untuk memformat tanggal sesuai.

1
20c