Search code examples
pythonpython-datetime

Why datetime.tzinfo instance needs a datetime to get its own attributes?


For a long time, I can not understand why a tzinfo object needs to be passed a external datetime to call its utcoffset(), tzname() methods, which look pretty much independent to an external time.

For example, I have to manually construct a useless datetime object to get a timezone's name?

from datetime import datetime
from dateutil.tz import gettz
tz = gettz("UTC")
tz.tzname(datetime.now()) # UTC

Looking at datetime.py source code, the implementation of timezone.tzname():

def tzname(self, dt):
    if isinstance(dt, datetime) or dt is None:
        if self._name is None:
            return self._name_from_offset(self._offset)
        return self._name
    raise TypeError("tzname() argument must be a datetime instance"
                    " or None")

I don't see dt is used at all.

Shouldn't a tzinfo know its own name, its offset from UTC? In what way a timezone's properties can depend on an external time point? In other words, why is the API designed this way?


Solution

  • Because a timezone's offset and name changes at different times of the year, and even historically:

    >>> tz
    <DstTzInfo 'Europe/Berlin' LMT+0:53:00 STD>
    >>> tz.tzname(datetime.now())
    'CEST'
    >>> tz.tzname(datetime(2018, 1, 1))
    'CET'
    >>> tz.tzname(datetime(1900, 1, 1))
    'LMT'
    >>> tz.utcoffset(datetime.now())
    datetime.timedelta(0, 7200)
    >>> tz.utcoffset(datetime(2018, 1, 1))
    datetime.timedelta(0, 3600)
    

    You don't see this with UTC, but that's rather the exception than the rule.