Время в API: передавайте момент, а не загадку

UTC, смещение и явное преобразование вместо неявного локального времени.

Строка 2026-09-09T10:00:00 не сообщает, в каком часовом поясе произошло событие. Если сервер и клиент понимают её по-разному, сортировка и дедлайны начинают расходиться. Для конкретного момента времени передавайте смещение или UTC.

Создать aware datetime

python
from datetime import datetime, timezone

now = datetime.now(timezone.utc)
print(now.isoformat())

Результат содержит смещение +00:00. Такой объект несёт информацию о часовом поясе, в отличие от naive datetime без tzinfo.

Преобразовать известное смещение

python
from datetime import datetime, timezone

event = datetime.fromisoformat(
    "2026-09-09T13:00:00+03:00"
)
print(event.astimezone(timezone.utc).isoformat())
# 2026-09-09T10:00:00+00:00

astimezone сохраняет момент и меняет его представление. Простая замена tzinfo не выполняет такого преобразования: она меняет интерпретацию исходных часов.

Оговорить контракт

Определите формат, допустимую точность и поведение для строк без смещения. Для поля occurred_at удобно требовать явный момент. Для даты рождения достаточно календарной даты: превращение её в полночь UTC обычно добавляет ненужную неоднозначность.

UTC не решает все задачи

Расписание «каждый день в девять по местному времени» описывает правило, а не единственный момент. Для него нужен региональный часовой пояс и отдельная обработка переходов времени. Фиксированное смещение не содержит этих правил.

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

Документация

Python: datetime ↗