Dukungan zona waktu di mssql-django

Artikel ini menjelaskan cara kerja field datetime yang mendukung zona waktu dengan SQL Server melalui backend mssql-django, serta cara memigrasikan data yang sudah ada saat Anda mengaktifkan dukungan zona waktu.

Cara kerja dukungan zona waktu

Setelan Django USE_TZ di settings.py menentukan apakah field datetime mendukung zona waktu:

Pengaturan Jenis kolom Behavior
USE_TZ=False datetime2 Menyimpan tanggal dan waktu naif tanpa informasi zona waktu.
USE_TZ=True datetimeoffset Menyimpan tanggal dan waktu yang menyertakan informasi zona waktu beserta offset UTC.

Note

Django secara bawaan menggunakan USE_TZ=False di semua versi, termasuk Django 5.x dan 6.0. Jika proyek Anda memerlukan dukungan zona waktu, Anda harus secara eksplisit mengatur USE_TZ=True di settings.py. Lihat Dukungan zona waktu di Django untuk informasi selengkapnya. Perhatikan bahwa datetimeoffset biasanya menggunakan lebih banyak penyimpanan daripada datetime2 untuk presisi tanda waktu yang sama, jadi pada tabel besar Anda harus memvalidasi paket penyimpanan dan kueri setelah migrasi.

Aktifkan dukungan zona waktu

Atur USE_TZ=True di settings.py Anda:

USE_TZ=True
TIME_ZONE = "UTC"

Ketika USE_TZ diaktifkan, Django menyimpan semua tanggalwaktu dalam UTC dan mengonversinya ke zona waktu lokal untuk ditampilkan.

Mulai dari mssql-django 1.7.2, backend juga menyelaraskan perilaku Django Now() dengan pembuatan SQL yang mendukung zona waktu ketika USE_TZ=True.

Memigrasikan kolom tanggalwaktu yang ada

Jika aplikasi Django Anda memiliki DateTimeField kolom sebelum mengaktifkan USE_TZ=True, Anda harus memigrasikan kolom datetime2 secara manual ke datetimeoffset dan mengonversi waktu lokal ke UTC.

Backend mssql-django menggunakan datetime2 sebagai tipe kolom yang mendasarinya untuk DateTimeField saat USE_TZ=False. Mengaktifkan USE_TZ tidak mengonversi kolom yang ada secara otomatis.

Dalam langkah-langkah berikut, ganti placeholder:

  • <table-name>: Nama tabel yang berisi kolom.
  • <datetime-column>: Nama kolom yang akan dikonversi.
  • <offset>: Offset zona waktu data Anda yang ada sebagai string dalam {+|-}HH:MM format (misalnya, '-05:00' untuk AS Timur).

Sampel kode dalam artikel ini menggunakan database sampel AdventureWorks2025 atau AdventureWorksDW2025, yang dapat Anda unduh dari halaman beranda Sampel dan Proyek Komunitas Microsoft SQL Server.

Langkah 1: Ubah jenis kolom

Jalankan SQL berikut pada setiap tabel yang memiliki kolom datetime2 . SQL Server secara implisit mengonversi nilai dan menetapkan +00:00 offset:

ALTER TABLE <table-name>
ALTER COLUMN <datetime-column> DATETIMEOFFSET;

Langkah 2: Konversi ke UTC

Setelah kolom adalah datetimeoffset, tag ulang setiap nilai dengan offset zona waktu lokal asli lalu konversi ke UTC:

UPDATE <table-name>
SET <datetime-column> = TODATETIMEOFFSET(<datetime-column>, <offset>) AT TIME ZONE 'UTC';

TODATETIMEOFFSET menggantikan bagian offset dari nilai datetimeoffset sehingga tanda waktu mencerminkan waktu lokal asli. AT TIME ZONE 'UTC' lalu mengonversi hasilnya menjadi UTC.

Important

Satu nilai offset tetap hanya berfungsi jika semua nilai sumber memiliki offset yang sama. Jika data Anda mencakup transisi waktu musim panas, tentukan offset berdasarkan tanggal atau gunakan strategi konversi berbasis nama zona waktu alih-alih menerapkan satu offset tetap ke setiap baris.

SQL Server nama zona waktu

Gunakan nama zona waktu Windows saat mengonversi dengan AT TIME ZONE. Contoh umum:

Wilayah SQL Server nama zona waktu Tanggal transisi DST (2026)
AS Timur Eastern Standard Time 8 Mar – 1 Nov
US Tengah Central Standard Time 8 Mar – 1 Nov
Pasifik AS Pacific Standard Time 8 Mar – 1 Nov
UTC UTC Tidak ada (tidak ada DST)
Eropa/London GMT Standard Time 29 Mar – 25 Okt

Untuk daftar lengkap, kueri SQL Server:

SELECT name, current_utc_offset, is_currently_dst
FROM sys.time_zone_info
ORDER BY name;

Lihat sys.time_zone_info untuk dokumentasi lengkap.

Contoh: Konversi Waktu Timur AS ke UTC (dengan mempertimbangkan DST)

Contoh ini menggunakan tabel skema yang ada AdventureWorks2025 dan menunjukkan penanganan DST yang benar selama migrasi:

-- Test with a DST transition date (March 8, 2026)
SELECT TOP 10 SalesOrderID,
             CAST (OrderDate AS DATETIME2) AS OriginalDateTime2,
             (CAST (OrderDate AS DATETIME2) AT TIME ZONE 'Eastern Standard Time') AS EasternTime,
             (CAST (OrderDate AS DATETIME2) AT TIME ZONE 'Eastern Standard Time' AT TIME ZONE 'UTC') AS ConvertedToUtc
FROM Sales.SalesOrderHeader
WHERE MONTH(OrderDate) = 3 AND DAY(OrderDate) = 8
ORDER BY SalesOrderID;

Tip

Selalu uji konversi zona waktu dengan data yang mencakup tanggal transisi DST. Kueri sebelumnya menguji tanggal 8 Maret (spring forward), yaitu saat Waktu Timur berubah dari EST (UTC-5) menjadi EDT (UTC-4).

Untuk memigrasikan tabel aplikasi Anda, terapkan pola konversi yang sama AT TIME ZONE ke kolom Anda sendiri DateTimeField . Untuk setiap tabel, tambahkan kolom datetimeoffset dan isi dari kolom yang ada:

ALTER TABLE [your_schema].[your_table] 
ADD [date_column_datetimeoffset] datetimeoffset NULL;

UPDATE [your_schema].[your_table]
SET [date_column_datetimeoffset] = CAST([old_date_column] AS DATETIME2) AT TIME ZONE 'Eastern Standard Time' AT TIME ZONE 'UTC';

Setelah Anda memverifikasi hasil konversi, letakkan kolom lama dan ganti nama yang baru:

ALTER TABLE [your_schema].[your_table]
DROP COLUMN [old_date_column];

EXECUTE sp_rename '[your_schema].[your_table].[date_column_datetimeoffset]', 'date_column', 'COLUMN';

Gunakan nama zona waktu SQL Server Windows yang cocok dengan wilayah data sumber Anda. Untuk informasi selengkapnya, lihat sys.time_zone_info.

Langkah 3: Menyelesaikan migrasi Django

Setelah mengonversi kolom database, ikuti dokumentasi Django tentang migrasi proyek yang dimulai sebelum dukungan zona waktu ditambahkan.

Important

Jalankan migrasi ini pada semua DateTimeField kolom di semua tabel. Kolom yang hilang menghasilkan penanganan zona waktu yang salah untuk bidang tersebut.

Limitations

  • Zona waktu dan timedeltas: Tidak semua operasi yang melibatkan zona waktu dan timedeltas didukung sepenuhnya. Untuk informasi selengkapnya, lihat Batasan dan fitur yang tidak didukung di mssql-django.
  • Aritmetika dengan datetime: Operasi pangkat sisi kanan dan aritmetika dengan nilai datetime mungkin tidak berfungsi seperti yang diharapkan ketika dukungan zona waktu diaktifkan.