zoneinfo — IANA 时区支持 — Python 文档

来自菜鸟教程
Python/docs/3.9/library/zoneinfo
跳转至:导航、​搜索

zoneinfo — IANA 时区支持

3.9 版中的新功能。



zoneinfo 模块提供了一个具体的时区实现来支持最初在 PEP 615 中指定的 IANA 时区数据库。 默认情况下,zoneinfo 使用系统的时区数据(如果可用); 如果没有可用的系统时区数据,库将回退到使用 PyPI 上可用的第一方 tzdata 包。

也可以看看

模块:日期时间
提供 timedatetime 类型,ZoneInfo 类旨在与这些类型一起使用。
封装 tzdata
由 CPython 核心开发人员维护的第一方包,用于通过 PyPI 提供时区数据。


使用 ZoneInfo

ZoneInfodatetime.tzinfo 抽象基类的具体实现,旨在通过构造函数,datetime 附加到 tzinfo .replace 方法或 datetime.astimezone

>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta

>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00

>>> dt.tzname()
'PDT'

以这种方式构造的日期时间与日期时间算术兼容,并且无需进一步干预即可处理夏令时转换:

>>> dt_add = dt + timedelta(days=1)

>>> print(dt_add)
2020-11-01 12:00:00-08:00

>>> dt_add.tzname()
'PST'

这些时区还支持 PEP 495 中引入的 fold 属性。 在导致时间不明确的偏移转换期间(例如夏令时到标准时间转换),从 before 转换的偏移用于 fold=0 和偏移 after[ X212X]过渡时使用fold=1,例如:

>>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-11-01 01:00:00-07:00

>>> print(dt.replace(fold=1))
2020-11-01 01:00:00-08:00

从另一个时区转换时,折叠将设置为正确的值:

>>> from datetime import timezone
>>> LOS_ANGELES = ZoneInfo("America/Los_Angeles")
>>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc)

>>> # Before the PDT -> PST transition
>>> print(dt_utc.astimezone(LOS_ANGELES))
2020-11-01 01:00:00-07:00

>>> # After the PDT -> PST transition
>>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES))
2020-11-01 01:00:00-08:00

数据源

zoneinfo 模块不直接提供时区数据,而是从系统时区数据库或第一方 PyPI 包 tzdata(如果有)中拉取时区信息。 一些系统,尤其是 Windows 系统,没有可用的 IANA 数据库,因此对于需要时区数据的跨平台兼容性项目,建议声明对 tzdata 的依赖。 如果系统数据和 tzdata 都不可用,所有对 ZoneInfo 的调用都会引发 ZoneInfoNotFoundError

配置数据源

调用 ZoneInfo(key) 时,构造函数首先在 TZPATH 中指定的目录中搜索与 key 匹配的文件,失败时在 tzdata 包中查找匹配项。 可以通过三种方式配置此行为:

  1. 默认的 TZPATH 如果没有另外指定,可以在 编译时间 配置。
  2. TZPATH 可以使用 环境变量 进行配置。
  3. runtime 中,可以使用 reset_tzpath() 函数来操作搜索路径。

编译时配置

默认的 TZPATH 包括时区数据库的几个常见部署位置(在 Windows 上除外,其中没有“众所周知”的时区数据位置)。 在 POSIX 系统上,下游分发者和那些从源代码构建 Python 的人知道他们的系统时区数据部署在哪里可以通过指定编译时选项 TZPATH(或者更有可能的是 [ X243X] 标志 --with-tzpath),它应该是一个由 os.pathsep 分隔的字符串。

在所有平台上,配置的值可用作 sysconfig.get_config_var() 中的 TZPATH 键。


环境配置

初始化 TZPATH 时(在导入时或不带参数调用 reset_tzpath() 时),zoneinfo 模块将使用环境变量 [X182X ],如果存在,设置搜索路径。

PYTHONTZPATH
这是一个 os.pathsep 分隔的字符串,包含要使用的时区搜索路径。 它必须只包含绝对路径而不是相对路径。 PYTHONTZPATH 中指定的相对组件将不会被使用,否则指定相对路径时的行为是实现定义的; CPython 将引发 InvalidTZPathWarning,但其他实现可以随意忽略错误组件或引发异常。

要将系统设置为忽略系统数据而使用 tzdata 包,请设置 PYTHONTZPATH=""


运行时配置

TZ 搜索路径也可以在运行时使用 reset_tzpath() 函数进行配置。 这通常不是一个可取的操作,尽管在需要使用特定时区路径(或需要禁用对系统时区的访问)的测试功能中使用它是合理的。


ZoneInfo 类

class zoneinfo.ZoneInfo(key)

一个具体的 datetime.tzinfo 子类,表示由字符串 key 指定的 IANA 时区。 对主构造函数的调用将始终返回比较相同的对象; 换句话说,通过 ZoneInfo.clear_cache() 禁止缓存失效,对于 key 的所有值,以下断言将始终为真:

a = ZoneInfo(key)
b = ZoneInfo(key)
assert a is b

key 必须采用相对的、规范化的 POSIX 路径的形式,没有上级引用。 如果传递了不符合要求的键,构造函数将引发 ValueError

如果没有找到匹配 key 的文件,构造函数将引发 ZoneInfoNotFoundError

ZoneInfo 类有两个备用构造函数:

classmethod ZoneInfo.from_file(fobj, /, key=None)

从返回字节的类文件对象构造 ZoneInfo 对象(例如 以二进制模式打开的文件或 io.BytesIO 对象)。 与主构造函数不同, this 总是构造一个新对象。

key 参数为 __str__()__repr__() 设置区域名称。

通过这个构造函数创建的对象不能被pickle(参见pickling)。

classmethod ZoneInfo.no_cache(key)

绕过构造函数缓存的备用构造函数。 它与主构造函数相同,但在每次调用时返回一个新对象。 这最有可能用于测试或演示目的,但它也可用于创建具有不同缓存失效策略的系统。

通过此构造函数创建的对象在 unpickled 时也将绕过反序列化过程的缓存。

警告

使用此构造函数可能会以令人惊讶的方式更改日期时间的语义,只有在您知道需要时才使用它。

还可以使用以下类方法:

classmethod ZoneInfo.clear_cache(*, only_keys=None)

一种使 ZoneInfo 类上的缓存失效的方法。 如果没有传递参数,则所有缓存都将失效,并且对每个键的主构造函数的下一次调用将返回一个新实例。

如果将键名的迭代传递给 only_keys 参数,则只会从缓存中删除指定的键。 传递给 only_keys 但未在缓存中找到的键将被忽略。

警告

调用此函数可能会以令人惊讶的方式使用 ZoneInfo 更改日期时间的语义; 这会修改进程范围的全局状态,因此可能会产生广泛的影响。 仅在您知道需要时才使用它。

该类有一个属性:

ZoneInfo.key

这是一个只读的 属性 ,它返回传递给构造函数的 key 的值,它应该是 IANA 时区数据库中的查找键(例如 America/New_YorkEurope/ParisAsia/Tokyo)。

对于从文件构建的区域,没有指定 key 参数,这将设置为 None

笔记

尽管将这些值暴露给最终用户是一种比较常见的做法,但这些值被设计为表示相关区域的主键,而不一定是面向用户的元素。 像 CLDR(Unicode 通用语言环境数据存储库)这样的项目可用于从这些键中获取更多用户友好的字符串。

字符串表示

ZoneInfo 对象上调用 str 时返回的字符串表示默认使用 ZoneInfo.key 属性(请参阅属性文档中的使用说明):

>>> zone = ZoneInfo("Pacific/Kwajalein")
>>> str(zone)
'Pacific/Kwajalein'

>>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone)
>>> f"{dt.isoformat()} [{dt.tzinfo}]"
'2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'

对于从没有指定 key 参数的文件构造的对象,str 回退到调用 repr()ZoneInforepr 是实现定义的,在版本之间不一定稳定,但保证不是有效的 ZoneInfo 密钥。


Pickle 序列化

ZoneInfo 对象不是序列化所有转换数据,而是通过键序列化,并且 ZoneInfo 对象从文件构造(即使是那些指定了 key 的值)不能被腌制。

ZoneInfo 文件的行为取决于它的构造方式:

  1. ZoneInfo(key):当用主构造函数构造时,一个ZoneInfo对象是通过key序列化的,反序列化时,反序列化过程使用主构造函数,因此预计它们是相同的对象作为对同一时区的其他引用。 例如,如果 europe_berlin_pkl 是一个包含从 ZoneInfo("Europe/Berlin") 构造的泡菜的字符串,人们会期望以下行为:

    >>> a = ZoneInfo("Europe/Berlin")
    >>> b = pickle.loads(europe_berlin_pkl)
    >>> a is b
    True
  2. ZoneInfo.no_cache(key):从缓存绕过构造函数构造时,ZoneInfo对象也是按key序列化的,但是反序列化时,反序列化过程使用缓存绕过构造函数。 如果 europe_berlin_pkl_nc 是一个包含从 ZoneInfo.no_cache("Europe/Berlin") 构造的泡菜的字符串,人们会期望以下行为:

    >>> a = ZoneInfo("Europe/Berlin")
    >>> b = pickle.loads(europe_berlin_pkl_nc)
    >>> a is b
    False
  3. ZoneInfo.from_file(fobj, /, key=None):从文件构造时,ZoneInfo 对象在酸洗时引发异常。 如果最终用户想要腌制从文件构造的 ZoneInfo,建议他们使用包装器类型或自定义序列化函数:通过键序列化或存储文件对象的内容并对其进行序列化。

这种序列化方法要求所需键的时区数据在序列化和反序列化端都可用,类似于在序列化和反序列化环境中预期存在对类和函数的引用的方式。 这也意味着在使用不同版本的时区数据的环境中解压 ZoneInfo 时,无法保证结果的一致性。


功能

zoneinfo.available_timezones()

获取包含时区路径上任何位置可用的 IANA 时区的所有有效密钥的集合。 每次调用该函数时都会重新计算。

此功能仅包含规范区域名称,不包括“特殊”区域,例如 posix/right/ 目录下的区域,或 posixrules 区域。

警告

此函数可能会打开大量文件,因为判断时区路径上的文件是否为有效时区的最佳方法是读取开头的“魔术字符串”。

笔记

这些值并非旨在向最终用户公开; 对于面向用户的元素,应用程序应该使用诸如 CLDR(Unicode 通用语言环境数据存储库)之类的东西来获得更多用户友好的字符串。 另请参阅有关 ZoneInfo.key 的警告说明。

zoneinfo.reset_tzpath(to=None)

设置或重置模块的时区搜索路径 (TZPATH)。 当不带参数调用时,TZPATH 设置为默认值。

调用 reset_tzpath 不会使 ZoneInfo 缓存失效,因此对主要 ZoneInfo 构造函数的调用将仅在缓存的情况下使用新的 TZPATH错过。

to 参数必须是字符串的 序列os.PathLike 而不是字符串,所有这些都必须是绝对路径。 ValueError 如果传递的不是绝对路径,则会引发。


全局变量

zoneinfo.TZPATH

表示时区搜索路径的只读序列——当从一个键构造一个 ZoneInfo 时,键被连接到 TZPATH 中的每个条目,并使用找到的第一个文件。

TZPATH 可能只包含绝对路径,从不包含相对路径,无论它是如何配置的。

zoneinfo.TZPATH指向的对象可能会因为调用reset_tzpath()而发生变化,所以建议使用zoneinfo.TZPATH而不是导入TZPATHzoneinfo 或将长期变量分配给 zoneinfo.TZPATH

有关配置时区搜索路径的更多信息,请参阅 配置数据源


异常和警告

exception zoneinfo.ZoneInfoNotFoundError
在构建 ZoneInfo 对象失败时引发,因为在系统上找不到指定的键。 这是 KeyError 的子类。
exception zoneinfo.InvalidTZPathWarning
PYTHONTZPATH 包含将被过滤掉的无效组件时引发,例如相对路径。