为什么 python timezone.utc 和 ZoneInfo("UTC") 不是等效的 tzinfo 对象?如何检查它们是同一个TZ?

问题描述 投票:0回答:1

为什么这些不相等?

>>> 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'
python timezone zoneinfo
1个回答
0
投票

至于为什么

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)。

时区的比较(如“时区规则”中)是一个更微妙的问题,这取决于您的需求。给定两个日期时间,您可以例如

  • 比较实际的时区(规则),即如果两个日期时间都“属于”tz X,其中X是IANA数据库标识符
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
  • 仅比较 UTC 的偏移量,即日期时间字段(小时分钟等)可以直接比较:
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
等的时区。

© www.soinside.com 2019 - 2024. All rights reserved.