zoneinfo --- IANA 时区支持

3.9 新版功能.


zoneinfo 模块根据 PEP 615 的最初说明提供了具体的时区实现来支持 IANA 时区数据库。 按照默认设置,zoneinfo 会在可能的情况下使用系统的时区数据;如果系统时区数据不可用,该库将回退为使用 PyPI 上提供的 tzdata 第一方包。

参见

模块: datetime

提供 timedatetime 类型,ZoneInfo 类被设计为可配合这两个类型使用。

tzdata

由 CPython 核心开发者维护以通过 PyPI 提供时区数据的第一方包。

使用 ZoneInfo

ZoneInfodatetime.tzinfo 抽象基类的具体实现,其目标是通过构造器、 datetime.replace 方法或 datetime.astimezone 来与 tzinfo 建立关联:

>>> 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。 在可能导致时间歧义的时差转换中(例如夏令时到标准时的转换),当 fold=0 时会使用转换 之前 的时差,而当 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

当执行来自另一时区的转换时,fold 将被设置为正确的值:

>>> 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. 运行时,搜索路径可使用 reset_tzpath() 函数来修改。

编译时配置

默认的 TZPATH 包括一些时区数据库的通用布署位置(Windows 除外,该系统没有时区数据的“通用”位置)。 在 POSIX 系统中,下游分发者和从源码编译 Python 的开发者知道系统时区数据布署位置,他们可以通过指定编译时选项 TZPATH (或者更常见的是通过 configure 旗标 --with-tzpath) 来改变默认的时区路径,该选项应当是一个由 os.pathsep 分隔的字符串。

在所有平台上,配置值会在 sysconfig.get_config_var() 中以 TZPATH 键的形式提供。

环境配置

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

PYTHONTZPATH

这是一个以 os.pathsep 分隔的字符串,其中包含要使用的时区搜索路径。 它必须仅由绝对路径而非相对路径组成。 在 PYTHONTZPATH 中指定的相对路径部分将不会被使用,但在其他情况下当指定相对路径时的行为该实现是有定义的;CPython 将引发 InvalidTZPathWarning,而其他实现可自由地忽略错误部分或是引发异常。

要设置让系统忽略系统数据并改用 tzdata 包,请设置 PYTHONTZPATH=""

运行时配置

TZ 搜索路径也可在运行时使用 reset_tzpath() 函数来配置。 通常并不建议如此操作,不过在需要使用指定时区路径(或者需要禁止访问系统时区)的测试函数中使用它则是合理的。

ZoneInfo

class zoneinfo.ZoneInfo(key)

一个具体的 datetime.tzinfo 子类,它代表一个由字符串 key 所指定的 IANA 时区。 对主构造器的调用将总是返回可进行标识比较的对象;但是另一种方式,对所有的 key 值通过 ZoneInfo.clear_cache() 禁止缓存失效,对以下断言将总是为真值:

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

key 必须采用相对的标准化 POSIX 路径的形式,其中没有对上一层级的引用。 如果传入了不合要求的键则构造器将引发 ValueError

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

ZoneInfo 类具有两个替代构造器:

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

基于一个返回字节串的文件类对象(例如一个以二进制模式打开的文件或是一个 io.BytesIO 对象)构造 ZoneInfo 对象。 不同于主构造器,此构造器总是会构造一个新对象。

key 形参设置时区名称以供 __str__()__repr__() 使用。

由此构造器创建的对象不可被封存 (参见 pickling)。

classmethod ZoneInfo.no_cache(key)

一个绕过构造器缓存的替代构造器。 它与主构造器很相似,但每次调用都会返回一个新对象。 此构造器在进行测试或演示时最为适用,但它也可以被用来创建具有不同缓存失效策略的系统。

由此构造器创建的对象在被解封时也会绕过反序列化进程的缓存。

警告

使用此构造器可以会以令人惊讶的方式改变日期时间对象的语义,只有在你确定你的需求时才使用它。

也可以使用以下的类方法:

classmethod ZoneInfo.clear_cache(*, only_keys=None)

一个可在 ZoneInfo 类上禁用缓存的方法。 如果不传入参数,则会禁用所有缓存并且下次对每个键调用主构造器将返回一个新实例。

如果将一个键名称的可迭代对象传给 only_keys 形参,则将只有指定的键会被从缓存中移除。 传给 only_keys 但在缓存中找不到的键会被忽略。

警告

发起调用此函数可能会以令人惊讶的方式改变使用 ZoneInfo 的日期时间对象的语义;这会修改进程范围内的全局状态并因此可能产生大范围的影响。 只有在你确定你的需求时才使用它。

该类具有一个属性:

ZoneInfo.key

这是一个只读的 attribute,它返回传给构造器的 key 的值,该值应为一个 IANA 时区数据库的查找键 (例如 America/New_York, Europe/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 键。

封存序列化

ZoneInfo 对象的序列化是基于键的,而不是序列化所有过渡数据,并且基于文件构造的 ZoneInfo 对象(即使是指定了 key 值的对象)不能被封存。

The behavior of a ZoneInfo file depends on how it was constructed:

  1. ZoneInfo(key): When constructed with the primary constructor, a ZoneInfo object is serialized by key, and when deserialized, the deserializing process uses the primary and thus it is expected that these are expected to be the same object as other references to the same time zone. For example, if europe_berlin_pkl is a string containing a pickle constructed from ZoneInfo("Europe/Berlin"), one would expect the following behavior:

    >>> a = ZoneInfo("Europe/Berlin")
    >>> b = pickle.loads(europe_berlin_pkl)
    >>> a is b
    True
    
  2. ZoneInfo.no_cache(key): When constructed from the cache-bypassing constructor, the ZoneInfo object is also serialized by key, but when deserialized, the deserializing process uses the cache bypassing constructor. If europe_berlin_pkl_nc is a string containing a pickle constructed from ZoneInfo.no_cache("Europe/Berlin"), one would expect the following behavior:

    >>> a = ZoneInfo("Europe/Berlin")
    >>> b = pickle.loads(europe_berlin_pkl_nc)
    >>> a is b
    False
    
  3. ZoneInfo.from_file(fobj, /, key=None): When constructed from a file, the ZoneInfo object raises an exception on pickling. If an end user wants to pickle a ZoneInfo constructed from a file, it is recommended that they use a wrapper type or a custom serialization function: either serializing by key or storing the contents of the file object and serializing that.

This method of serialization requires that the time zone data for the required key be available on both the serializing and deserializing side, similar to the way that references to classes and functions are expected to exist in both the serializing and deserializing environments. It also means that no guarantees are made about the consistency of results when unpickling a ZoneInfo pickled in an environment with a different version of the time zone data.

函数

zoneinfo.available_timezones()

Get a set containing all the valid keys for IANA time zones available anywhere on the time zone path. This is recalculated on every call to the function.

This function only includes canonical zone names and does not include "special" zones such as those under the posix/ and right/ directories, or the posixrules zone.

警告

This function may open a large number of files, as the best way to determine if a file on the time zone path is a valid time zone is to read the "magic string" at the beginning.

注解

These values are not designed to be exposed to end-users; for user facing elements, applications should use something like CLDR (the Unicode Common Locale Data Repository) to get more user-friendly strings. See also the cautionary note on ZoneInfo.key.

zoneinfo.reset_tzpath(to=None)

Sets or resets the time zone search path (TZPATH) for the module. When called with no arguments, TZPATH is set to the default value.

Calling reset_tzpath will not invalidate the ZoneInfo cache, and so calls to the primary ZoneInfo constructor will only use the new TZPATH in the case of a cache miss.

The to parameter must be a sequence of strings or os.PathLike and not a string, all of which must be absolute paths. ValueError will be raised if something other than an absolute path is passed.

Globals

zoneinfo.TZPATH

A read-only sequence representing the time zone search path -- when constructing a ZoneInfo from a key, the key is joined to each entry in the TZPATH, and the first file found is used.

TZPATH may contain only absolute paths, never relative paths, regardless of how it is configured.

The object that zoneinfo.TZPATH points to may change in response to a call to reset_tzpath(), so it is recommended to use zoneinfo.TZPATH rather than importing TZPATH from zoneinfo or assigning a long-lived variable to zoneinfo.TZPATH.

For more information on configuring the time zone search path, see 配置数据源.

Exceptions and warnings

exception zoneinfo.ZoneInfoNotFoundError

Raised when construction of a ZoneInfo object fails because the specified key could not be found on the system. This is a subclass of KeyError.

exception zoneinfo.InvalidTZPathWarning

Raised when PYTHONTZPATH contains an invalid component that will be filtered out, such as a relative path.