Вы обнаружили ошибку в 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
, и эта ошибка будет исправлена в следующем выпуске.
Примечание : Этот ответ был отредактирован после того, как я нашел причину и исправление ошибки.