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