在Windows上获取本地时区名称(Python 3.9 zoneinfo)

10

在查看 Python 3.9 的 zoneinfo 模块时,我想知道它是否还提供了一种方便的选项来检索 Windows 系统上的本地时间区域设置。

在 GNU/Linux 上,您可以执行以下操作:

from datetime import datetime
from zoneinfo import ZoneInfo

naive = datetime(2020, 6, 11, 12)
aware = naive.replace(tzinfo=ZoneInfo('localtime'))

但是在Windows上,这会引发

ZoneInfoNotFoundError: '未找到具有本地时间键的时区'

那么我是否仍然需要使用第三方库?例如:

import time
import dateutil

tzloc = dateutil.tz.gettz(time.tzname[time.daylight])
aware = naive.replace(tzinfo=tzloc)

由于time.tzname[time.daylight]返回一个本地化的名称(在我的情况下是德语,例如“Mitteleuropäische Sommerzeit”),因此这也不起作用:

aware = naive.replace(tzinfo=ZoneInfo(tzloc))

有什么想法吗?


补充说明:如果要在Python < 3.9上尝试此操作,请使用backports(也请参考此答案):

pip install backports.zoneinfo
pip install tzdata # needed on Windows
2个回答

10
您不需要使用zoneinfo来使用系统本地时区。当调用datetime.astimezone时,可以简单地传递None(或省略)时区。
从文档中可以看到:

如果没有提供参数(或使用tz=None),则假定为系统本地时区。转换后的日期时间实例的.tzinfo属性将设置为一个时区实例,该实例的区域名称和偏移量来自于操作系统。

因此:
from datetime import datetime

naive = datetime(2020, 6, 11, 12)
aware = naive.astimezone()

如果当前日期和您尝试印刷的日期之间的夏令时不同,那么这是否有效? - Mark Ransom
@MarkRansom - 是的。 - Matt Johnson-Pint
我刚刚仔细检查了一下,你说得对。这是一个很棒的隐藏功能! - Mark Ransom
1
这并不是在Windows上的100%解决方案,例如在我的系统上,datetime.now().astimezone().strftime('%Y-%m-%d %H:%M:%I%Z%z')会产生"2023-05-31 12:49:12Central Daylight Time-0500"而不是"2023-05-31 12:49:12CDT-0500"。然而,datetime.now().astimezone(zoneinfo.ZoneInfo('America/Chicago')).strftime('%Y-%m-%d %H:%M:%I%Z%z')会产生预期的结果'2023-05-31 12:57:12CDT-0500'。 - royce3

6

astimezone(None) 虽然很方便,但有时您可能想要获取您的时区的 IANA名称,而不是Windows认为最适合您的。

tzlocal 的第4版 也将使用 zoneinfo 来实现这一点,同时通过弃用包装器pytz 兼容:

>>> import tzlocal
>>> print(tzlocal.get_localzone())
Europe/Berlin
>>> print(repr(tzlocal.get_localzone()))
_PytzShimTimezone(zoneinfo.ZoneInfo(key='Europe/Berlin'), 'Europe/Berlin')

[更新] 在版本5中,pytz的弃用shim已被移除,请参见tzlocal的自述文件

>>> print(tzlocal.get_localzone())
Europe/Berlin
>>> print(repr(tzlocal.get_localzone()))
zoneinfo.ZoneInfo(key='Europe/Berlin')

请注意,tzlocal的版本5进行了更改,使其无法在日志处理程序内使用,请参见https://github.com/regebro/tzlocal/issues/147。 - royce3
@royce3 感谢提示,已经有一段时间没有使用该模块了。看起来这是一个循环导入的 bug,请参考 https://github.com/jobec/rfc5424-logging-handler/pull/47 - FObersteiner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接