арифметика даты и времени в Python 3.9.1

Пробуя новую поддержку zoneinfo в python3.9.1, я заметил, что разница во времени объектов, учитывающих дату и время, отличается от тех, которые создаются pytz, как показано в выводе следующей программы:

import datetime,zoneinfo,pytz
from sys import version_info
print(f'Python{version_info.major}.{version_info.minor}{version_info.micro}'
f' pytz{pytz.__version__}')
Athens=zoneinfo.ZoneInfo('Europe/Athens')
f='%Y-%m-%d %H:%M:%S'
d=[datetime.datetime.strptime('2020-10-25 00:00:00',f),
   datetime.datetime.strptime('2020-10-25 23:59:59',f)]
print('naive   ',d[1]-d[0])
d=[x.astimezone(Athens) for x in d]
print('zoneinfo',d[1]-d[0])
d=[datetime.datetime.strptime('2020-10-25 00:00:00',f),
   datetime.datetime.strptime('2020-10-25 23:59:59',f)]
athens=pytz.timezone('Europe/Athens')
print('pytz as ',d[1].astimezone(athens)-d[0].astimezone(athens))
print('pytz loc',athens.localize(d[1])-athens.localize(d[0]))

Python3.91 pytz2020.4
naive    23:59:59
zoneinfo 23:59:59
pytz as  1 day, 0:59:59
pytz loc 1 day, 0:59:59

Похоже, что собственная поддержка часовых поясов игнорирует тот факт, что 2020-10-25 был днем ​​перехода с летнего на зимнее время, и поэтому продолжительность этого дня составляла 25 часов. Что мне не хватает?


person NameOfTheRose    schedule 03.12.2020    source источник
comment
при ближайшем рассмотрении я думаю, что это то, что вы пропали. Значение timedelta, которое вы получаете из осведомленного datetime с помощью zoneinfo tzinfo, учитывает DST; показывает время на стене. То же самое и для dateutil, кстати. С часовыми поясами pytz это не так. Это боль ^^   -  person MrFuppes    schedule 03.12.2020
comment
@MrFuppes, спасибо. Мне нужно обдумать это.   -  person NameOfTheRose    schedule 03.12.2020
comment
Надеюсь, это поможет. Также обратите внимание на ответ Пола на связанный вопрос и обсуждение, которое я провел с ним в комментариях. Я до сих пор нахожу всю эту стену timedelta трудной для понимания. Мне нравится думать о времени в физическом смысле, но, возможно, это слишком наивно в реальном мире ^^   -  person MrFuppes    schedule 03.12.2020
comment
@MrFuppes, его случай хорошо представлен, но не убедителен. Противоинтуитивное иногда бывает просто эвфемизмом слова «неправильно». Документирование ошибки не делает ее функцией.   -  person NameOfTheRose    schedule 04.12.2020
comment
Не уверен, насколько хорошо это задокументировано, по крайней мере, для меня это не очевидно в документы. Более того, пакеты Python делают это иначе, чем стандартная библиотека, как вы отметили. Другой пример, pandas рассматривает наивное datetime как UTC, тогда как datetime Python принимает местное время. Может сбивать с толку ... Думаю, с самого начала некоторые вещи можно было сделать иначе.   -  person MrFuppes    schedule 04.12.2020


Ответы (1)


Иллюстрация моего комментария; осведомленное datetime с tzinfo, установленным с ZoneInfo от zoneinfo, возвращает timedelta времени стены. Если вы сделаете то же самое с pytz.timezone осведомленным о дате и времени, вы получите абсолютное время timedelta.

from datetime import datetime
from zoneinfo import ZoneInfo
import pytz
from sys import version_info

print(f'Python {version_info.major}.{version_info.minor}{version_info.micro} pytz {pytz.__version__}')
# Python 3.90 pytz 2020.4

d=[datetime.fromisoformat('2020-10-25 00:00:00'), datetime.fromisoformat('2020-10-25 23:59:59')]

Athens = ZoneInfo('Europe/Athens')
print('wall time diff, zoneinfo:', d[1].replace(tzinfo=Athens)-d[0].replace(tzinfo=Athens))
# wall time diff, zoneinfo: 23:59:59

athens = pytz.timezone('Europe/Athens')
print('absolute time diff, pytz:', athens.localize(d[1])-athens.localize(d[0]))
# absolute time diff, pytz: 1 day, 0:59:59

# to get absolute time delta with zoneinfo:
utc = ZoneInfo('UTC')
print('absolute time diff, zoneinfo:', d[1].replace(tzinfo=Athens).astimezone(utc)
                                      -d[0].replace(tzinfo=Athens).astimezone(utc))
# absolute time diff, zoneinfo: 1 day, 0:59:59
person MrFuppes    schedule 03.12.2020