Ответ вслух Middle Стандартная библиотека обновлено

Даты и таймзоны в бэкенде

Вопрос

Расскажите, как вы работаете с датами и таймзонами в бэкенде. Какие были баги?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Образцовый ответ: «Правило простое: внутри системы только aware-время в UTC. Получаю его через datetime.now(timezone.utc), в PostgreSQL храню в timestamptz, по API отдаю в ISO 8601 со смещением.

Что должно прозвучать в ответе

  • Всё внутри в UTC, aware-объекты

  • Перевод в зону пользователя только при показе, zoneinfo

  • В БД тип с таймзоной (timestamptz)

  • Переходы на летнее время и «несуществующие» часы

  • Смешение naive и aware, utcnow

  • Сравнение дат и границы дня в зоне пользователя

Что могут спросить следом

  • Как посчитать «начало дня» для пользователя во Владивостоке?
  • Чем timedelta(days=1) отличается от «завтра в то же время» при переходе на летнее время?

Разбор

Образцовый ответ: «Правило простое: внутри системы только aware-время в UTC. Получаю его через datetime.now(timezone.utc), в PostgreSQL храню в timestamptz, по API отдаю в ISO 8601 со смещением. В зону пользователя перевожу только на границе: при показе и при вычислениях, которые зависят от календаря пользователя, например «отчёт за сегодня». Для этого zoneinfo.ZoneInfo из стандартной библиотеки. Типичные баги, которые видел: naive-время из utcnow(), которое потом приняли за локальное, и сдвиг на три часа; границы дня, посчитанные в UTC, из-за чего утренние заказы пользователей из Владивостока попадали во вчерашний отчёт; в странах с переходом на летнее время прибавление timedelta(days=1) даёт не ту же стрелку часов. Поэтому календарную арифметику делаю в локальной зоне, а хранение и сравнение в UTC».

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.