'Check that python tzinfo is UTC

I'm trying to write up a general way to verify that a given tzinfo represents UTC.

So far, the best solution I've come up with is the following:

def check_tzinfo_is_utc(tz_info: Optional[Type[tzinfo]]) -> bool:
    is_tzinfo_utc = False
    try:
        is_tzinfo_utc = tz_info.utcoffset(datetime.utcnow()) == timedelta(0)
    except AttributeError:
        logger.warning(f"tzinfo is not a tzinfo object: {tz_info}")
    return is_tzinfo_utc

where the idea is to try to use the provided tzinfo to get the utc offset of an arbitrary native datetime object.

If the tzinfo is not correct, the except statement should capture it, and the function return False.

I wrote this function with a limited number of use cases in mind, do you see some potential improvements and edge cases where this function would fail?

Thanks!



Solution 1:[1]

comparing the tzinfo object against a set of objects that you consider "UTC" might be a more robust option, e.g.

from datetime import datetime, timezone, timedelta
from zoneinfo import ZoneInfo
import pytz
import dateutil

# what to consider UTC
is_utc = (
    timezone(timedelta(0)),
    timezone.utc,
    pytz.utc,
    ZoneInfo("UTC"),
    dateutil.tz.UTC, # <- this one is not hashable, so use a tuple, not a set
)


def dt_has_utclike_tz(dt, is_utc):
    if dt.tzinfo is None:
        return False
    return dt.tzinfo in is_utc


for z in (
    None,
    ZoneInfo("Europe/London"),
    pytz.utc,
    timezone(timedelta(hours=-5)),
    dateutil.tz.UTC,
):
    print(z, dt_has_utclike_tz(datetime(2022, 1, 1, tzinfo=z), is_utc))
    print(
        "UTC offset zero?", datetime(2022, 1, 1, tzinfo=z).utcoffset() == timedelta(0)
    )

# None False
# UTC offset zero? False
# Europe/London False
# UTC offset zero? True # <- note this one ...
# UTC True
# UTC offset zero? True
# UTC-05:00 False
# UTC offset zero? False
# tzutc() True
# UTC offset zero? True

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1