1:mod:`zoneinfo` --- IANA time zone support
2==========================================
3
4.. module:: zoneinfo
5    :synopsis: IANA time zone support
6
7.. versionadded:: 3.9
8
9.. moduleauthor:: Paul Ganssle <[email protected]>
10.. sectionauthor:: Paul Ganssle <[email protected]>
11
12**Source code:** :source:`Lib/zoneinfo`
13
14--------------
15
16The :mod:`zoneinfo` module provides a concrete time zone implementation to
17support the IANA time zone database as originally specified in :pep:`615`. By
18default, :mod:`zoneinfo` uses the system's time zone data if available; if no
19system time zone data is available, the library will fall back to using the
20first-party `tzdata`_ package available on PyPI.
21
22.. seealso::
23
24    Module: :mod:`datetime`
25        Provides the :class:`~datetime.time` and :class:`~datetime.datetime`
26        types with which the :class:`ZoneInfo` class is designed to be used.
27
28    Package `tzdata`_
29        First-party package maintained by the CPython core developers to supply
30        time zone data via PyPI.
31
32.. include:: ../includes/wasm-notavail.rst
33
34Using ``ZoneInfo``
35------------------
36
37:class:`ZoneInfo` is a concrete implementation of the :class:`datetime.tzinfo`
38abstract base class, and is intended to be attached to ``tzinfo``, either via
39the constructor, the :meth:`datetime.replace <datetime.datetime.replace>`
40method or :meth:`datetime.astimezone <datetime.datetime.astimezone>`::
41
42    >>> from zoneinfo import ZoneInfo
43    >>> from datetime import datetime, timedelta
44
45    >>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
46    >>> print(dt)
47    2020-10-31 12:00:00-07:00
48
49    >>> dt.tzname()
50    'PDT'
51
52Datetimes constructed in this way are compatible with datetime arithmetic and
53handle daylight saving time transitions with no further intervention::
54
55    >>> dt_add = dt + timedelta(days=1)
56
57    >>> print(dt_add)
58    2020-11-01 12:00:00-08:00
59
60    >>> dt_add.tzname()
61    'PST'
62
63These time zones also support the :attr:`~datetime.datetime.fold` attribute
64introduced in :pep:`495`.  During offset transitions which induce ambiguous
65times (such as a daylight saving time to standard time transition), the offset
66from *before* the transition is used when ``fold=0``, and the offset *after*
67the transition is used when ``fold=1``, for example::
68
69    >>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
70    >>> print(dt)
71    2020-11-01 01:00:00-07:00
72
73    >>> print(dt.replace(fold=1))
74    2020-11-01 01:00:00-08:00
75
76When converting from another time zone, the fold will be set to the correct
77value::
78
79    >>> from datetime import timezone
80    >>> LOS_ANGELES = ZoneInfo("America/Los_Angeles")
81    >>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc)
82
83    >>> # Before the PDT -> PST transition
84    >>> print(dt_utc.astimezone(LOS_ANGELES))
85    2020-11-01 01:00:00-07:00
86
87    >>> # After the PDT -> PST transition
88    >>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES))
89    2020-11-01 01:00:00-08:00
90
91Data sources
92------------
93
94The ``zoneinfo`` module does not directly provide time zone data, and instead
95pulls time zone information from the system time zone database or the
96first-party PyPI package `tzdata`_, if available. Some systems, including
97notably Windows systems, do not have an IANA database available, and so for
98projects targeting cross-platform compatibility that require time zone data, it
99is recommended to declare a dependency on tzdata. If neither system data nor
100tzdata are available, all calls to :class:`ZoneInfo` will raise
101:exc:`ZoneInfoNotFoundError`.
102
103.. _zoneinfo_data_configuration:
104
105Configuring the data sources
106****************************
107
108When ``ZoneInfo(key)`` is called, the constructor first searches the
109directories specified in :data:`TZPATH` for a file matching ``key``, and on
110failure looks for a match in the tzdata package. This behavior can be
111configured in three ways:
112
1131. The default :data:`TZPATH` when not otherwise specified can be configured at
114   :ref:`compile time <zoneinfo_data_compile_time_config>`.
1152. :data:`TZPATH` can be configured using :ref:`an environment variable
116   <zoneinfo_data_environment_var>`.
1173. At :ref:`runtime <zoneinfo_data_runtime_config>`, the search path can be
118   manipulated using the :func:`reset_tzpath` function.
119
120.. _zoneinfo_data_compile_time_config:
121
122Compile-time configuration
123^^^^^^^^^^^^^^^^^^^^^^^^^^
124
125The default :data:`TZPATH` includes several common deployment locations for the
126time zone database (except on Windows, where there are no "well-known"
127locations for time zone data). On POSIX systems, downstream distributors and
128those building Python from source who know where their system
129time zone data is deployed may change the default time zone path by specifying
130the compile-time option ``TZPATH`` (or, more likely, the :option:`configure
131flag --with-tzpath <--with-tzpath>`), which should be a string delimited by
132:data:`os.pathsep`.
133
134On all platforms, the configured value is available as the ``TZPATH`` key in
135:func:`sysconfig.get_config_var`.
136
137.. _zoneinfo_data_environment_var:
138
139Environment configuration
140^^^^^^^^^^^^^^^^^^^^^^^^^
141
142When initializing :data:`TZPATH` (either at import time or whenever
143:func:`reset_tzpath` is called with no arguments), the ``zoneinfo`` module will
144use the environment variable ``PYTHONTZPATH``, if it exists, to set the search
145path.
146
147.. envvar:: PYTHONTZPATH
148
149    This is an :data:`os.pathsep`-separated string containing the time zone
150    search path to use. It must consist of only absolute rather than relative
151    paths. Relative components specified in ``PYTHONTZPATH`` will not be used,
152    but otherwise the behavior when a relative path is specified is
153    implementation-defined; CPython will raise :exc:`InvalidTZPathWarning`, but
154    other implementations are free to silently ignore the erroneous component
155    or raise an exception.
156
157To set the system to ignore the system data and use the tzdata package
158instead, set ``PYTHONTZPATH=""``.
159
160.. _zoneinfo_data_runtime_config:
161
162Runtime configuration
163^^^^^^^^^^^^^^^^^^^^^
164
165The TZ search path can also be configured at runtime using the
166:func:`reset_tzpath` function. This is generally not an advisable operation,
167though it is reasonable to use it in test functions that require the use of a
168specific time zone path (or require disabling access to the system time zones).
169
170
171The ``ZoneInfo`` class
172----------------------
173
174.. class:: ZoneInfo(key)
175
176    A concrete :class:`datetime.tzinfo` subclass that represents an IANA time
177    zone specified by the string ``key``. Calls to the primary constructor will
178    always return objects that compare identically; put another way, barring
179    cache invalidation via :meth:`ZoneInfo.clear_cache`, for all values of
180    ``key``, the following assertion will always be true:
181
182    .. code-block:: python
183
184        a = ZoneInfo(key)
185        b = ZoneInfo(key)
186        assert a is b
187
188    ``key`` must be in the form of a relative, normalized POSIX path, with no
189    up-level references. The constructor will raise :exc:`ValueError` if a
190    non-conforming key is passed.
191
192    If no file matching ``key`` is found, the constructor will raise
193    :exc:`ZoneInfoNotFoundError`.
194
195
196The ``ZoneInfo`` class has two alternate constructors:
197
198.. classmethod:: ZoneInfo.from_file(fobj, /, key=None)
199
200    Constructs a ``ZoneInfo`` object from a file-like object returning bytes
201    (e.g. a file opened in binary mode or an :class:`io.BytesIO` object).
202    Unlike the primary constructor, this always constructs a new object.
203
204    The ``key`` parameter sets the name of the zone for the purposes of
205    :py:meth:`~object.__str__` and :py:meth:`~object.__repr__`.
206
207    Objects created via this constructor cannot be pickled (see `pickling`_).
208
209.. classmethod:: ZoneInfo.no_cache(key)
210
211    An alternate constructor that bypasses the constructor's cache. It is
212    identical to the primary constructor, but returns a new object on each
213    call. This is most likely to be useful for testing or demonstration
214    purposes, but it can also be used to create a system with a different cache
215    invalidation strategy.
216
217    Objects created via this constructor will also bypass the cache of a
218    deserializing process when unpickled.
219
220    .. TODO: Add "See `cache_behavior`_" reference when that section is ready.
221
222    .. caution::
223
224        Using this constructor may change the semantics of your datetimes in
225        surprising ways, only use it if you know that you need to.
226
227The following class methods are also available:
228
229.. classmethod:: ZoneInfo.clear_cache(*, only_keys=None)
230
231    A method for invalidating the cache on the ``ZoneInfo`` class. If no
232    arguments are passed, all caches are invalidated and the next call to
233    the primary constructor for each key will return a new instance.
234
235    If an iterable of key names is passed to the ``only_keys`` parameter, only
236    the specified keys will be removed from the cache. Keys passed to
237    ``only_keys`` but not found in the cache are ignored.
238
239    .. TODO: Add "See `cache_behavior`_" reference when that section is ready.
240
241    .. warning::
242
243        Invoking this function may change the semantics of datetimes using
244        ``ZoneInfo`` in surprising ways; this modifies process-wide global state
245        and thus may have wide-ranging effects. Only use it if you know that you
246        need to.
247
248The class has one attribute:
249
250.. attribute:: ZoneInfo.key
251
252    This is a read-only :term:`attribute` that returns the value of ``key``
253    passed to the constructor, which should be a lookup key in the IANA time
254    zone database (e.g. ``America/New_York``, ``Europe/Paris`` or
255    ``Asia/Tokyo``).
256
257    For zones constructed from file without specifying a ``key`` parameter,
258    this will be set to ``None``.
259
260    .. note::
261
262        Although it is a somewhat common practice to expose these to end users,
263        these values are designed to be primary keys for representing the
264        relevant zones and not necessarily user-facing elements.  Projects like
265        CLDR (the Unicode Common Locale Data Repository) can be used to get
266        more user-friendly strings from these keys.
267
268String representations
269**********************
270
271The string representation returned when calling :py:class:`str` on a
272:class:`ZoneInfo` object defaults to using the :attr:`ZoneInfo.key` attribute (see
273the note on usage in the attribute documentation)::
274
275    >>> zone = ZoneInfo("Pacific/Kwajalein")
276    >>> str(zone)
277    'Pacific/Kwajalein'
278
279    >>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone)
280    >>> f"{dt.isoformat()} [{dt.tzinfo}]"
281    '2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'
282
283For objects constructed from a file without specifying a ``key`` parameter,
284``str`` falls back to calling :func:`repr`. ``ZoneInfo``'s ``repr`` is
285implementation-defined and not necessarily stable between versions, but it is
286guaranteed not to be a valid ``ZoneInfo`` key.
287
288.. _pickling:
289
290Pickle serialization
291********************
292
293Rather than serializing all transition data, ``ZoneInfo`` objects are
294serialized by key, and ``ZoneInfo`` objects constructed from files (even those
295with a value for ``key`` specified) cannot be pickled.
296
297The behavior of a ``ZoneInfo`` file depends on how it was constructed:
298
2991. ``ZoneInfo(key)``: When constructed with the primary constructor, a
300   ``ZoneInfo`` object is serialized by key, and when deserialized, the
301   deserializing process uses the primary and thus it is expected that these
302   are expected to be the same object as other references to the same time
303   zone.  For example, if ``europe_berlin_pkl`` is a string containing a pickle
304   constructed from ``ZoneInfo("Europe/Berlin")``, one would expect the
305   following behavior:
306
307   .. code-block:: pycon
308
309       >>> a = ZoneInfo("Europe/Berlin")
310       >>> b = pickle.loads(europe_berlin_pkl)
311       >>> a is b
312       True
313
3142. ``ZoneInfo.no_cache(key)``: When constructed from the cache-bypassing
315   constructor, the ``ZoneInfo`` object is also serialized by key, but when
316   deserialized, the deserializing process uses the cache bypassing
317   constructor. If ``europe_berlin_pkl_nc`` is a string containing a pickle
318   constructed from ``ZoneInfo.no_cache("Europe/Berlin")``, one would expect
319   the following behavior:
320
321   .. code-block:: pycon
322
323       >>> a = ZoneInfo("Europe/Berlin")
324       >>> b = pickle.loads(europe_berlin_pkl_nc)
325       >>> a is b
326       False
327
3283. ``ZoneInfo.from_file(fobj, /, key=None)``: When constructed from a file, the
329   ``ZoneInfo`` object raises an exception on pickling. If an end user wants to
330   pickle a ``ZoneInfo`` constructed from a file, it is recommended that they
331   use a wrapper type or a custom serialization function: either serializing by
332   key or storing the contents of the file object and serializing that.
333
334This method of serialization requires that the time zone data for the required
335key be available on both the serializing and deserializing side, similar to the
336way that references to classes and functions are expected to exist in both the
337serializing and deserializing environments. It also means that no guarantees
338are made about the consistency of results when unpickling a ``ZoneInfo``
339pickled in an environment with a different version of the time zone data.
340
341Functions
342---------
343
344.. function:: available_timezones()
345
346    Get a set containing all the valid keys for IANA time zones available
347    anywhere on the time zone path. This is recalculated on every call to the
348    function.
349
350    This function only includes canonical zone names and does not include
351    "special" zones such as those under the ``posix/`` and ``right/``
352    directories, or the ``posixrules`` zone.
353
354    .. caution::
355
356        This function may open a large number of files, as the best way to
357        determine if a file on the time zone path is a valid time zone is to
358        read the "magic string" at the beginning.
359
360    .. note::
361
362        These values are not designed to be exposed to end-users; for user
363        facing elements, applications should use something like CLDR (the
364        Unicode Common Locale Data Repository) to get more user-friendly
365        strings. See also the cautionary note on :attr:`ZoneInfo.key`.
366
367.. function:: reset_tzpath(to=None)
368
369    Sets or resets the time zone search path (:data:`TZPATH`) for the module.
370    When called with no arguments, :data:`TZPATH` is set to the default value.
371
372    Calling ``reset_tzpath`` will not invalidate the :class:`ZoneInfo` cache,
373    and so calls to the primary ``ZoneInfo`` constructor will only use the new
374    ``TZPATH`` in the case of a cache miss.
375
376    The ``to`` parameter must be a :term:`sequence` of strings or
377    :class:`os.PathLike` and not a string, all of which must be absolute paths.
378    :exc:`ValueError` will be raised if something other than an absolute path
379    is passed.
380
381Globals
382-------
383
384.. data:: TZPATH
385
386    A read-only sequence representing the time zone search path -- when
387    constructing a ``ZoneInfo`` from a key, the key is joined to each entry in
388    the ``TZPATH``, and the first file found is used.
389
390    ``TZPATH`` may contain only absolute paths, never relative paths,
391    regardless of how it is configured.
392
393    The object that ``zoneinfo.TZPATH`` points to may change in response to a
394    call to :func:`reset_tzpath`, so it is recommended to use
395    ``zoneinfo.TZPATH`` rather than importing ``TZPATH`` from ``zoneinfo`` or
396    assigning a long-lived variable to ``zoneinfo.TZPATH``.
397
398    For more information on configuring the time zone search path, see
399    :ref:`zoneinfo_data_configuration`.
400
401Exceptions and warnings
402-----------------------
403
404.. exception:: ZoneInfoNotFoundError
405
406    Raised when construction of a :class:`ZoneInfo` object fails because the
407    specified key could not be found on the system. This is a subclass of
408    :exc:`KeyError`.
409
410.. exception:: InvalidTZPathWarning
411
412    Raised when :envvar:`PYTHONTZPATH` contains an invalid component that will
413    be filtered out, such as a relative path.
414
415.. Links and references:
416
417.. _tzdata: https://pypi.org/project/tzdata/
418