この記事では、タイム ゾーン対応の datetime フィールドが、mssql-django バックエンドを介してSQL Serverと連携する方法と、タイム ゾーンのサポートを有効にしたときに既存のデータを移行する方法について説明します。
タイム ゾーンのサポートのしくみ
Django の settings.py 内の USE_TZ 設定は、datetime フィールドがタイムゾーン対応であるかどうかを制御します。
| Setting | 列の種類 | Behavior |
|---|---|---|
USE_TZ=False |
datetime2 | タイム ゾーン情報なしで単純な日時を格納します。 |
USE_TZ=True |
datetimeoffset | タイム ゾーン対応の日時を UTC オフセットで格納します。 |
Note
Django は、Django 5.x および 6.0 を含むすべてのバージョンで既定で USE_TZ=False されます。 プロジェクトでタイム ゾーンのサポートが必要な場合は、USE_TZ=Trueでsettings.pyを明示的に設定する必要があります。 詳細については、 Django でのタイム ゾーンのサポート を参照してください。
datetimeoffset では、通常、同じタイムスタンプ精度で datetime2 よりも多くのストレージが使用されるため、大規模なテーブルでは、移行後にストレージプランとクエリ プランを検証する必要があります。
タイム ゾーンのサポートを有効にする
settings.pyでUSE_TZ=Trueを設定:
USE_TZ=True
TIME_ZONE = "UTC"
USE_TZが有効になっている場合、Django はすべての datetime を UTC で格納し、表示のためにローカル タイム ゾーンに変換します。
mssql-django 1.7.2 以降では、バックエンドは Django Now()の動作を、USE_TZ=True時のタイム ゾーン対応 SQL 生成に合わせて調整します。
既存の datetime 列を移行する
DateTimeFieldを有効にする前に Django アプリにUSE_TZ=True列がある場合は、datetime2 列を datetimeoffset に手動で移行し、ローカル時刻を UTC に変換する必要があります。
mssql-django バックエンドでは、するときに、DateTimeFieldの基になる列の種類として USE_TZ=False が使用されます。
USE_TZを有効にしても、既存の列は自動的に変換されません。
次の手順では、プレースホルダーを置き換えます。
-
<table-name>: 列を含むテーブル名。 -
<datetime-column>: 変換する列名。 -
<offset>:{+|-}HH:MM形式の文字列としての既存のデータのタイム ゾーン オフセット (たとえば、米国東部の'-05:00')。
この記事のコード サンプルでは、AdventureWorks2025 または AdventureWorksDW2025 サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクト ホーム ページからダウンロードできます。
手順 1: 列の種類を変更する
datetime2 列を含む各テーブルで、次の SQL を実行します。 SQL Server値を暗黙的に変換し、+00:00 オフセットを割り当てます。
ALTER TABLE <table-name>
ALTER COLUMN <datetime-column> DATETIMEOFFSET;
手順 2: UTC に変換する
列が datetimeoffset に設定されたら、各値に元のローカル タイム ゾーン オフセットを再タグ付けし、UTC に変換します。
UPDATE <table-name>
SET <datetime-column> = TODATETIMEOFFSET(<datetime-column>, <offset>) AT TIME ZONE 'UTC';
TODATETIMEOFFSET は datetimeoffset 値のオフセット部分を置き換え、タイムスタンプに元のローカル時刻が反映されるようにします。
AT TIME ZONE 'UTC' 次に、結果を UTC に変換します。
Important
1 つの固定オフセットは、すべてのソース値が同じオフセットを共有する場合にのみ機能します。 データが夏時間の遷移にまたがる場合は、日付でオフセットを派生させるか、すべての行に 1 つの定数オフセットを適用するのではなく、タイム ゾーン名ベースの変換戦略を使用します。
SQL Server のタイム ゾーン名
AT TIME ZONEで変換するときは、Windowsタイム ゾーン名を使用します。 一般的な例:
| リージョン | SQL Server のタイムゾーン名 | DST の移行日 (2026) |
|---|---|---|
| 米国東部 | Eastern Standard Time |
3 月 8 日 – 11 月 1 日 |
| 米国中部 | Central Standard Time |
3 月 8 日 – 11 月 1 日 |
| 米国太平洋 | Pacific Standard Time |
3 月 8 日 – 11 月 1 日 |
| UTC | UTC |
なし (DST なし) |
| ヨーロッパ/ロンドン | GMT Standard Time |
3月29日~10月25日 |
完全な一覧については、SQL Serverクエリを実行します。
SELECT name, current_utc_offset, is_currently_dst
FROM sys.time_zone_info
ORDER BY name;
完全なドキュメントについては 、sys.time_zone_info を参照してください。
例: 米国東部標準時を UTC (DST 対応) に変換する
この例では、既存の AdventureWorks2025 スキーマ テーブルを使用し、移行中の正しい DST 処理を示します。
-- 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
DST の移行日にまたがるデータを使用して、常にタイム ゾーン変換をテストします。 前のクエリでは、3 月 8 日 (春先) がテストされます。これは東部時間が EST (UTC-5) から EDT (UTC-4) に変わるときです。
アプリケーション テーブルを移行するには、同じ AT TIME ZONE 変換パターンを独自の DateTimeField 列に適用します。 テーブルごとに datetimeoffset 列を追加し、既存の列からデータを設定します。
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';
変換結果を確認したら、古い列を削除し、新しい列の名前を変更します。
ALTER TABLE [your_schema].[your_table]
DROP COLUMN [old_date_column];
EXECUTE sp_rename '[your_schema].[your_table].[date_column_datetimeoffset]', 'date_column', 'COLUMN';
ソース データ リージョンと一致するSQL Server Windowsタイム ゾーン名を使用します。 詳細については、「sys.time_zone_info」 を参照してください。
手順 3: Django の移行を完了する
データベース列を変換した後、 タイム ゾーンのサポートが追加される前に開始されたプロジェクトの移行に関する Django のドキュメントに従ってください。
Important
すべてのテーブルのすべての DateTimeField 列でこの移行を実行します。 列が見つからないと、それらのフィールドのタイム ゾーン処理が正しくありません。
Limitations
- タイム ゾーンとタイムデルタ: タイム ゾーンとタイムデルタに関連するすべての操作が完全にサポートされているわけではありません。 詳細については、「 mssql-django の制限事項とサポートされていない機能」を参照してください。
- datetimes を使用した算術演算: タイム ゾーンのサポートが有効になっていると、右力と datetime 値を持つ算術演算が期待どおりに動作しない可能性があります。