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