В настоящее время я работаю над бэкэнд для системы календаря, которая возвращает наивные даты Python. Как работает внешний интерфейс, пользователь создает различные события календаря, а интерфейс возвращает наивную версию созданного события (например, если пользователь выбирает 5 октября 2020 года с 15:00 до 16:00, возвращается интерфейс datetime.datetime(2020, 10, 5, 15, 0, 0) как начало и datetime.datetime(2011, 10, 5, 16, 0, 0) в качестве конца.
Что мне нужно сделать, так это взять наивное datetime и преобразовать его в UTC для хранения в базе данных. Каждый пользователь системы уже указал свое предпочтение по часовому поясу, поэтому наивное datetime считается тем же часовым поясом, что и их часовое предпочтение. Очевидно, что данные должны храниться относительно UTC, так что если пользователи меняют свой часовой пояс, существующие события будут отображаться в правильное время, которое они запланировали.
Внешний интерфейс находится вне моего контроля, поэтому я не могу изменить данные, которые получаю. Дизайн базы данных также находится вне моего контроля, поэтому я не могу изменить, какие данные хранятся и как.
Вот приблизительный подход, который я сделал до сих пор:
import pytz
def convert_to_UTC(naive_datetime, user_tz_preference):
user_datetime = naive_datetime.replace(tzinfo=user_tz_preference)
utc_datetime = user_datetime.astimezone(pytz.utc)
Проблема, с которой я столкнулся, связана с летним временем сбережения:
>>> from datetime import datetime
>>> import pytz
>>> user_tz_preference = pytz.timezone('US/Pacific')
>>> naive_datetime = datetime(2011, 10, 26, 12, 0, 0)
>>> user_datetime = naive_datetime.replace(tzinfo=user_tz_preference)
>>> user_datetime
datetime.datetime(2011, 10, 26, 12, 0, tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:00 STD>)
>>> received_utc = user_datetime.astimezone(pytz.utc)
>>> received_utc
datetime.datetime(2011, 10, 26, 20, 0, tzinfo=<UTC>)
>>> expected_utc = datetime(2011, 10, 26, 19, 0, tzinfo=pytz.utc)
>>> expected_utc == received_utc
False
Обратите внимание, что использование "replace" устанавливает часовой пояс для PST вместо PDT независимо от даты, что дает ему смещение UTC на 8 часов вместо ожидаемого смещения DST на 7 часов, поэтому время заканчивается тем, что оно сохраняется некорректно.
Какие параметры у меня есть для преобразования наивного datetime в правильный PDT (или другой временной отклик DST) tzinfo?
(Кроме того, обратите внимание, что не все пользователи живут в часовом поясе, который наблюдает за DST, или могут жить в часовом поясе, который переключается в разное время, поэтому для того, чтобы сделать решение, такое как коррекция timedelta, до сохранения, мне понадобится чтобы узнать, поддерживает ли часовой пояс DST и в какие даты он переключается).