Почему я получаю разные результаты для pytz и dateutil для Самоа? - PullRequest
0 голосов
/ 02 сентября 2018

Я ожидал, что следующие два дадут тот же результат, но они этого не сделали. Почему это так?

Версия:

pytz==2018.5
python-dateutil==2.7.3

Пример 1: pytz

import datetime
import pytz

tz = pytz.timezone('Pacific/Apia')
today_utc = datetime.datetime(2011, 12, 30, 9, 59,
                              tzinfo=datetime.timezone.utc)
today_tz = today_utc.astimezone(tz)
print(today_tz.isoformat())

печатает 2011-12-29T23:59:00-10:00 (что правильно)

Пример 2: dateutil

import datetime
import dateutil.tz

tz = dateutil.tz.gettz('Pacific/Apia')
today_utc = datetime.datetime(2011, 12, 30, 9, 59,
                              tzinfo=datetime.timezone.utc)
today_tz = today_utc.astimezone(tz)
print(today_tz.isoformat())

печатает 2011-12-29T23:59:00+14:00 (что неверно)

1 Ответ

0 голосов
/ 02 сентября 2018

Вы обнаружили ошибку в dateutil, о которой я сейчас сообщил, и исправлено .

Ошибка была вызвана проблемой с тем, как "время стены" переходов было вычислено в dateutil, что делало некоторые предположения, которые не выполняются, когда базовое смещение часового пояса изменяется во время летнего времени, Немного расширив свой пример:

from datetime import datetime, timedelta
from dateutil import tz
import pytz

APIA = tz.gettz('Pacific/Apia')
APIA_p = pytz.timezone('Pacific/Apia')
dt0 = datetime.fromisoformat('2011-12-29T20:00-10:00')

for i in range(5):
    dt = (dt0 + timedelta(hours=i))
    dt_d = dt.astimezone(APIA)
    dt_p = dt.astimezone(APIA_p)
    print(f'{dt_d.isoformat()}, {dt_p.isoformat()}')

## Result:
# 2011-12-29T20:00:00-10:00, 2011-12-29T20:00:00-10:00
# 2011-12-29T21:00:00-10:00, 2011-12-29T21:00:00-10:00
# 2011-12-29T22:00:00-10:00, 2011-12-29T22:00:00-10:00
# 2011-12-29T23:00:00+14:00, 2011-12-29T23:00:00-10:00
# 2011-12-31T00:00:00+14:00, 2011-12-31T00:00:00+14:00

Вы можете видеть, что dateutil всегда правильно вычисляет дату и время, но когда isoformat вызывает utcoffset, изменение смещения происходит на 1 час раньше. Это потому, что astimezone звонит tzinfo.fromutc под колпак, а isoformat звонит utcoffset. dateutil хранит время перехода как в UTC, так и в местное время, время UTC используется в fromutc, а местное время используется в utcoffset, dst и tzname. Эта ошибка включала в себя чрезмерную компенсацию DST при расчете «времени стены» перехода во время переходов DST-> DST (которые встречаются крайне редко), поэтому она не повлияла на astimezone.

Итог - вы правильно используете pytz и dateutil, и эта ошибка будет исправлена ​​в следующем выпуске.

Примечание : Этот ответ был отредактирован после того, как я нашел причину и исправление ошибки.

...