объект `timedelta` не учитывает переход на летнее время - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь получить соответствующий диапазон времени для запроса в базе данных (где даты и время хранятся в UTC) в местном часовом поясе пользователя. Вот какое-то странное поведение, которое я обнаружил, что я не знаю, как обойти:

import pytz
from datetime import datetime, timedelta

local_tz = pytz.timezone("America/New_York")
utc = pytz.timezone("UTC")

start = local_tz.localize(datetime(2019, 11, 3))  # 2019-11-03 00:00:00-04:00
end = start + timedelta(days=1)  # 2019-11-04 00:00:00-04:00

start_utc = utc.normalize(start)  # 2019-11-03 04:00:00+00:00
end_utc = utc.normalize(end)  # 2019-11-04 04:00:00+00:00

utc.normalize(local_tz.localize(datetime(2019, 11, 4)))  # 2019-11-04 05:00:00+00:00

Изменение Летнего времени каким-то образом теряется при нормализации переменной end, созданной путем добавления timedeltaвозражать start. Почему это могло произойти?

1 Ответ

2 голосов
/ 05 ноября 2019

Не уверен относительно ожидаемого поведения в вычислениях datetime, но я просто объясню поведение из примеров общего кода.

pytz.localize создает экземпляр datetime с учетом часового пояса. Когда часовой пояс Нью-Йорка используется для localize простого времени, он назначает правильный часовой пояс, EDT до 3 ноября и EST для 4 ноября и позже. Давайте исключим timedelta здесь:

>>> import pytz
>>> from datetime import datetime, timedelta
>>> tz_ny = pytz.timezone("America/New_York")
>>> tz_ny.localize(datetime(2019, 11, 3))
datetime.datetime(2019, 11, 3, 0, 0, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
>>> tz_ny.localize(datetime(2019, 11, 4))
datetime.datetime(2019, 11, 4, 0, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)

Как видно, DstTzInfo отличаются, как и следовало ожидать, потому что NY DST заканчивается 3 ноября.

Образец общего кода создаетstart по localizing 3 ноября, который присваивает EDT как tzinfo объекту datetime (с использованием DST). Для создания end, timedelta из 1 дня добавляется к start, но tzinfo объекта datetime остается неизменным :

>>> start = tz_ny.localize(datetime(2019, 11, 3))
>>> start.tzinfo
<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>
>>> end = start + timedelta(days=1)
>>> end.tzinfo
<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>

Такend означает datetime для 4 ноября, но информация DstTzInfo остается такой же, как 3 ноября. И это отличается от localizing наивного datetime от 4 ноября, который не использует DST.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...