Локальное время не существует: DST при tz_localize в pandas

Филиал прислал журнал с локальными датами без часового пояса. Большую часть года привязка к Europe/Berlin работает, но в день перевода часов загрузка падает. В журнале есть 02:30, хотя весной такого местного времени не было. Осенью обратная проблема: одно и то же время встречается дважды.

tz_localize назначает зону наивному времени, не перемещая часы. Правила зоны определяют, существует ли этот момент и можно ли однозначно перевести его в UTC. Автоматически угадать реальный момент по одной строке 02:30 невозможно: источник должен передать смещение или другое различающее поле.

Как изменить решение

import pandas as pd
spring = pd.Series(pd.to_datetime(['2026-03-29 01:30',
                                       '2026-03-29 02:30']))
localized = spring.dt.tz_localize('Europe/Berlin', nonexistent='NaT')
assert localized.isna().tolist() == [False, True]
print(localized.isna().tolist())
fall = pd.Series(pd.to_datetime(['2026-10-25 02:30',
                                     '2026-10-25 02:30']))
resolved = fall.dt.tz_localize('Europe/Berlin', ambiguous=[True, False])
utc = resolved.dt.tz_convert('UTC')
assert (utc.iloc[1] - utc.iloc[0]) == pd.Timedelta(hours=1)
print(utc.tolist())

Весеннее несуществующее время отмечено NaT. Осенние одинаковые часы стали двумя разными моментами с разницей час. В массиве ambiguous мы явно сообщили, какая строка относится к летнему времени, а какая — к стандартному; это решение должно приходить из данных, а не из догадки обработчика.

Если источник умеет отдавать UTC или ISO-строку со смещением, принимайте именно её. Локальное представление можно восстановить для интерфейса позднее. Не используйте timezone с фиксированным смещением вместо именованной зоны для долгой истории: правила смещения меняются по календарю.

Что проверить на своих данных

Для запуска нужны pandas и база часовых поясов; на Windows при её отсутствии установите python -m pip install pandas tzdata. В тестах проверьте обычный день, весенний пропуск и осеннюю неоднозначность. Отдельно подтвердите число событий: исключение NaT из groupby может скрыть строки, отправленные на разбор.

Сдвиг nonexistent вперед до допустимого момента является бизнес-правилом исправления, а не восстановлением исходного факта. Несколько разных неверных часов могут попасть в одну точку и создать ложные совпадения. Для журналов аудита разумнее сохранить исходный текст, зону, ошибку локализации и идентификатор записи. Тогда повторная загрузка после уточнения источника сможет исправить конкретное событие, не меняя остальные.

Практика дальше

Когда время приведено к однозначным моментам, можно собирать групповые и скользящие расчёты. В тренажёре «NumPy и pandas» вы работаете с датами, очисткой таблиц и показателями по группам. Затем соединяете эти приёмы в обработке заказов и клиентском отчёте.

Посмотреть программу и практику курса

Источник: Локальное время не существует — официальная документация.

Другие задачи по теме: Календарь, пропуски и точность вычислений.

Продолжить на практике

  • NumPy и pandas: практический тренажёр ↗

    Бесплатный тренажёр NumPy и pandas для тех, кто знает основы Python. Научитесь очищать таблицы, объединять данные и собирать отчёты: 31 урок и 124 задачи с кодом и автоматической проверкой.