Поддержка часового пояса в mssql-django

В этой статье объясняется, как поля даты и времени, поддерживающие часовой пояс, работают с SQL Server через серверную mssql-django часть и как перенести существующие данные при включении поддержки часового пояса.

Как работает поддержка часового пояса

Настройка Django USE_TZ в settings.py определяет, зависят ли поля datetime от часового пояса:

Setting Тип столбца Behavior
USE_TZ=False datetime2 Хранит наивные значения даты и времени без информации о часовом поясе.
USE_TZ=True datetimeoffset Сохраняет значения даты и времени с указанием часового пояса и смещением относительно UTC.

Note

Django по умолчанию использует USE_TZ=False во всех версиях, включая Django 5.x и 6.0. Если вашему проекту нужна поддержка часовых поясов, необходимо явно указать USE_TZ=True в вашем settings.py. Дополнительные сведения см. в разделе "Поддержка часового пояса" в Django . Обратите внимание, что datetimeoffset обычно использует больше хранилища, чем datetime2 для той же точности метки времени, поэтому в больших таблицах следует проверять планы хранения и запросов после миграции.

Включение поддержки часового пояса

Задайте USE_TZ=True в поле settings.py:

USE_TZ=True
TIME_ZONE = "UTC"

Если USE_TZ этот параметр включен, Django хранит все даты и времени в формате UTC и преобразует их в локальный часовой пояс для отображения.

Начиная с mssql-django версии 1.7.2, серверный модуль также приводит поведение Django Now() в соответствие с генерацией SQL с учетом часового пояса при USE_TZ=True.

Перенос существующих столбцов datetime

Если в вашем приложении Django до включения USE_TZ=True были столбцы DateTimeField, необходимо вручную выполнить миграцию столбцов datetime2 в datetimeoffset и преобразовать локальное время в UTC.

Серверная часть mssql-django использует datetime2 в качестве базового типа данных столбца для DateTimeField при USE_TZ=False. Включение USE_TZ не преобразует существующие столбцы автоматически.

В следующих шагах замените местозаполнители:

  • <table-name>: имя таблицы, содержащей столбец.
  • <datetime-column> — имя столбца для преобразования.
  • <offset>: смещение часового пояса существующих данных в виде строки в {+|-}HH:MM формате (например, '-05:00' для восточной части США).

Примеры кода в этой статье используют базу данных образца AdventureWorks2025 или AdventureWorksDW2025, которую можно скачать с домашней страницы образцов и проектов сообщества Microsoft SQL Server и.

Шаг 1. Изменение типов столбцов

Запустите следующий SQL в каждой таблице с столбцами datetime2 . 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

Одно фиксированное смещение работает только в том случае, если все исходные значения имеют одно и то же смещение. Если ваши данные охватывают переходы на летнее и зимнее время, определяйте смещение по дате или используйте стратегию преобразования с использованием имени часового пояса вместо того, чтобы применять одно и то же постоянное смещение к каждой строке.

имена часовых поясов SQL Server

Используйте названия часовых поясов Windows при преобразовании с помощью AT TIME ZONE. Распространенные примеры:

Region имя часового пояса SQL Server Дата перехода DST (2026)
Восточная часть США Eastern Standard Time 8 марта – 1 ноября
Центральная часть США Central Standard Time 8 марта – 1 ноября
Тихоокеанский регион США Pacific Standard Time 8 марта – 1 ноября
UTC UTC Нет (нет DST)
Европа/Лондон GMT Standard Time 29 марта – 25 октября

Для получения полного списка запросите SQL Server:

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

Полную документацию см. в sys.time_zone_info.

Пример: Преобразование восточного времени США в UTC (с учётом летнего времени)

В этом примере используется существующая 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. В предыдущем запросе проверяется 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

  • Часовые пояса и таймдельтасы: не все операции, включающие часовые пояса и timedeltas, полностью поддерживаются. Дополнительные сведения см. в разделе "Ограничения" и неподдерживаемые функции в mssql-django.
  • Арифметические операции с датой и временем: возведение в степень с правым операндом и арифметические операции со значениями даты и времени могут работать не так, как ожидается, если включена поддержка часовых поясов.