为什么这些不相等?
>>> from datetime import datetime
>>> from datetime import timedelta
>>> from datetime import timezone
>>> from zoneinfo import ZoneInfo
>>> from zoneinfo import ZoneInfoNotFoundError
>>> dt_tz = datetime.now(tz=timezone.utc)
>>> dt_zi = dt_tz.astimezone(tz=ZoneInfo("UTC"))
>>> dt_tz
datetime.datetime(2024, 5, 1, 23, 15, 24, 3560, tzinfo=datetime.timezone.utc)
>>> dt_zi
datetime.datetime(2024, 5, 1, 23, 15, 24, 3560, tzinfo=zoneinfo.ZoneInfo(key='UTC'))
>>> dt_tz == dt_zi
True
>>> dt_tz.tzinfo == dt_zi.tzinfo
False
如果两个
datetime
tz 感知对象是使用 timezone
或 ZoneInfo
创建的,如何检查它们是否具有等效的 TZ?乍一看,这些东西的目的是做同样的事情,但它们并不完全可以互操作。例如,没有 ZoneInfo.astimezone()
转换。
预期建议使用某些第三方库的答案,这些答案都可以,但强烈的偏好是使用 python 内置包(python 3 >= 3.11)。
>>> dt_tz.tzname()
'UTC'
>>> dt_zi.tzname()
'UTC'
>>> dt_tz.tzname() == dt_zi.tzname()
True
>>> dt_tz.tzinfo
datetime.timezone.utc
>>> type(dt_tz.tzinfo)
<class 'datetime.timezone'>
>>> ZoneInfo(dt_tz.tzname())
zoneinfo.ZoneInfo(key='UTC')
但这并不能推广到 UTC 之外:(
>>> dt_ny = datetime.now().astimezone(ZoneInfo("America/New_York"))
>>> dt_ny
datetime.datetime(2024, 5, 1, 19, 38, 53, 69087, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
>>> ts = dt_ny.isoformat()
>>> ts
'2024-05-01T19:38:53.069087-04:00'
>>> ts_dt = datetime.fromisoformat(ts)
>>> ts_dt
datetime.datetime(2024, 5, 1, 19, 38, 53, 69087, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))
>>> ts_dt.tzname()
'UTC-04:00'
>>> ZoneInfo(ts_dt.tzname())
zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key UTC-04:00'
至于为什么
timezone.utc
和 ZoneInfo("UTC")
不被认为是相等的:它们是不同类的实例,并且对象具有不同的来源。
zoneinfo.ZoneInfo
查询您系统上的 IANA tz 数据库 (src)。在 Linux 或 Mac 上尝试 find /usr/share/zoneinfo -name "UTC"
。在 Windows 上,IANA 数据库需要通过 tzdata
软件包单独安装。datetime.timezone.utc
是时区类对象的预定义实例,偏移量为零,名称字段设置为 UTC (src)。时区的比较(如“时区规则”中)是一个更微妙的问题,这取决于您的需求。给定两个日期时间,您可以例如
from datetime import datetime
from zoneinfo import ZoneInfo
chi = datetime(2024,1,1,tzinfo=ZoneInfo("America/Chicago"))
ny = datetime(2024,1,1,tzinfo=ZoneInfo("America/New_York"))
print(chi.tzinfo.key == ny.tzinfo.key) # note: ZoneInfo objects required as tzinfo!
# False
print(chi.utcoffset() == ny.utcoffset())
# False
some_dt = datetime.fromisoformat("2024-01-01T00:00-06:00")
print(chi.utcoffset() == some_dt.utcoffset())
# True
print(chi.replace(tzinfo=None) == some_dt.replace(tzinfo=None))
# True
请注意,对于情况 #1,您可能需要编写 tz 包特定的代码,即检查 tzinfo 是否具有来自
pytz
、dateutil
等的时区。