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