Даты и таймзоны в бэкенде
Вопрос
Расскажите, как вы работаете с датами и таймзонами в бэкенде. Какие были баги?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Всё внутри в 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 ошибок.