Python WindowsLinuxmacOSPython 3

Python: В Python неправильно сравниваются даты с часовыми поясами

  • Обновлено
  • Чтение ≈ 3 минуты

Краткий ответ

Сравнение дат Python даёт ошибку или неверный порядок, если одни datetime имеют часовой пояс, а другие — нет, либо используется локальное время без учёта смены летнего времени.

В этой статье
  1. Что произошло и когда проявляется ошибка
  2. Причины и диагностические признаки
  3. Подробная пошаговая диагностика и исправление
  4. Как проверить, что проблема устранена
  5. Если исправление не помогло

#Что произошло и когда проявляется ошибка

Сравнение дат Python даёт ошибку или неверный порядок, если одни datetime имеют часовой пояс, а другие — нет, либо используется локальное время без учёта смены летнего времени.

#Причины и диагностические признаки

Возможная причинаКак узнатьЧто делать
Naive и aware одновременноУ одной даты tzinfo is None, у другой известен часовой пояс.TypeError: can't compare offset-naive and offset-aware datetimesЯвно определить смысл исходной локальной даты.
Неверно применяется replace(tzinfo=...)replace назначает пояс, но не преобразует момент времени.Ожидаемое местное время сдвигается на часыДля конвертации использовать astimezone.
Смена летнего времениЛокальная дата без уточнения fold может быть неоднозначной.В осенний переход есть два одинаковых локальных часаХранить UTC и явный пояс, уточнять источник времени.

#Подробная пошаговая диагностика и исправление

  1. 1. Проверьте входные значенияВ копии скрипта выведите для обеих дат isoformat(), tzinfo, utcoffset(); если дата содержит персональные сведения, не записывайте её в общедоступные журналы. Значение без +03:00, Z или иного смещения нужно трактовать по договорённости с источником, а не автоматически как UTC.
  2. Пример кода по теме
    Python
    Выполняйте после создания объектов datetime a и b; у naive datetime utcoffset() обычно None.
    print(a.isoformat(), a.tzinfo, a.utcoffset())
    print(b.isoformat(), b.tzinfo, b.utcoffset())
  1. 2. Нормализуйте даты с известными поясами в UTCДля aware-дат выполняйте astimezone(timezone.utc) перед сравнением. Оба значения должны иметь определённый часовой пояс; это сохраняет момент времени и предотвращает путаницу между регионом и смещением.
  2. Пример кода по теме
    Python
    Образец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
    from datetime import datetime, timezone
    a = datetime.fromisoformat("2026-01-01T12:00:00+03:00")
    b = datetime.fromisoformat("2026-01-01T09:30:00+00:00")
    print(a.astimezone(timezone.utc) < b.astimezone(timezone.utc))
  1. 3. Для исходного локального времени уточните зонуЕсли входное время заведомо задано по Москве, используйте ZoneInfo("Europe/Moscow") только после подтверждения источника, затем приведите его к UTC. Для неизвестной исходной зоны не назначайте UTC автоматически. На некоторых системах потребуется актуальная база часовых поясов.
  2. Пример кода по теме
    Python
    Образец кода для файла .py в тестовой копии проекта; перед внедрением замените имена файлов на реальные.
    from datetime import datetime, timezone
    from zoneinfo import ZoneInfo
    local = datetime(2026, 11, 2, 12, 0, tzinfo=ZoneInfo("Europe/Moscow"))
    print(local.astimezone(timezone.utc).isoformat())
  1. 4. Проверьте пограничные датыСоздайте тесты для одного и того же момента с разными смещениями, переходов через полночь и дат перевода часов в фактическом регионе. Не делайте вывод о совпадении момента по совпадению часов на циферблате. Для неоднозначных местных часов согласуйте правило обработки fold на уровне приложения.
  1. 5. Исправьте сохранение и отображениеДля событий храните однозначный момент времени (обычно UTC) и при показе пользователю преобразуйте через astimezone в нужный регион. Повторите сравнение на тестовой базе и сверяйте упорядочивание двух контрольных событий.

#Как проверить, что проблема устранена

Даты с известными часовыми поясами сортируются в порядке фактических моментов времени, без TypeError и с тестами на границах суток.

#Если исправление не помогло

Если источник присылает время без зоны, до исправления формата обмена документируйте допущение, а в неоднозначных периодах запрашивайте смещение. replace(tzinfo=timezone.utc) не преобразует произвольное местное время в UTC.

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.