roob
roob

Reputation: 2529

How to get timezone rules version used by datetime?

In John Skeet's blog post about handling timezone information when storing future datetimes, he suggests storing the version of timezone rules in the database along with the local time and timezone id.

His example:

ID: 1
Name: KindConf
LocalStart: 2022-07-10T09:00:00
Address: Europaplein 24, 1078 GZ Amsterdam, Netherlands
TimeZoneId: Europe/Amsterdam
UtcStart: 2022-07-10T07:00:00Z
TimeZoneRules: 2019a

In python, how do you get the version of timezone rules used by datetime? For example:

date.astimezone(zoneinfo.ZoneInfo('US/Pacific'))

Upvotes: 2

Views: 707

Answers (2)

Niko Fohr
Niko Fohr

Reputation: 33830

This is a POSIX-only solution, works with tzdata v.2018a+:

import os
from pathlib import Path  
import re
import zoneinfo 


def get_system_tzdata_version():
    """
    Get the used tzdata version

    NOTE: Only supports tzdata versions 2018a and
    later, as the version info was added to tzdata.zi
    in tzdata version 2018a.

    Returns
    -------
    version: str | None
        The version of the system tzdata.
        If version could not be read from tzdata.zi,
        return None.
    """

    # This is a file that contains a copy of all data
    # in the tzdata database. It has been part of the
    # tzdata since release 2017c.
    tzdata_zi_fname = "tzdata.zi"

    if os.name == "nt":  # Windows
        raise NotImplementedError("Currently, only POSIX is supported")

    # Assuming we are in posix system
    for p in zoneinfo.TZPATH:
        p = Path(p)
        tzdata_zi = p / tzdata_zi_fname
        if p.exists() and tzdata_zi.exists():
            break

    with open(tzdata_zi) as f:
        contents = f.read()

    match = re.match(r"^\s*#\s*version\s+(?P<version>.*)\n", contents)

    if not match:
        # Could not find version string from the tzdata.zi file
        return None

    return match.group("version")

Explanation

  • zoneinfo by default uses the system timezone information, which on POSIX systems is coming from the tzdata (system) package.
  • The locations where zoneinfo reads for tzdata data are listed in zoneinfo.TZPATH
  • The version info of the tzdata database has been written to a file called tzdata.zi since tzdata version 2018a. [tzdata NEWS]

Upvotes: 0

roob
roob

Reputation: 2529

The method of getting timezone rules depends on the library used to create the tzinfo instance.

If using pytz, the timezone database used is the Olson timezone database.

import pytz
print(pytz.OLSEN_VERSION)  # e.g. 2021a

When using zoneinfo, the system's timezone data is used by default.

From the docs: By default, 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 tzdata package available on PyPI.

There are two options:

  1. Find a platform specific method of getting the version number
  2. Setup zoneinfo with the tzdata library, which makes the timezone version number readily available.

For option 2:

To setup zoneinfo to ignore the system data and use the tzdata package instead, set the environment variable PYTHONTZPATH=""

The IANA version number is exported by tzdata:

import tzdata
print(tzdata.IANA_VERSION). # e.g. 2021e

Upvotes: 2

Related Questions