[Datetime-SIG] how does PEP-495 help improve dateutil, pytz timezone packages?

Akira Li 4kir4.1i at gmail.com
Wed Aug 26 03:20:34 CEST 2015

Alexander Belopolsky <alexander.belopolsky at gmail.com> writes:

> On Tue, Aug 25, 2015 at 7:19 PM, Akira Li <4kir4.1i at gmail.com> wrote:
>> Here's a distilled example:
>>   >>> from datetime import datetime, timezone
>>   >>> datetime(2013, 10, 28,
>> tzinfo=timezone.utc).astimezone().strftime('%Z%z')
>> If you *disable tm_gmtoff attribute* then it produces UTC+04:00+0400.
>> That differs from the expected output MSK+0400, like the same code
>> demonstrates if you enable the attribute. Notice (direct quote): "if
>> tm_gmtoff or tm_zone are not available" above.
> Of course!  That's why we exposed tm_gmtoff attribute in time.time_struct
> on *all platfoms* IIRC.  It's been a long time, by I recall that we went to
> some great lengths to emulate tm_gmtoff by comparing the results of
> localtime calls to those of gmtime.   Could it be that we missed some
> corner cases?  Sure.  But your "if tm_gmtoff or tm_zone are not available"
> sounds like complaining that after
>>>> del datetime.timezone
> the datetime module does not support even the UTC timezone!

Whether or not tm_gmtoff is available depends on C library. The time
module documentation says [1]:

  .. versionchanged:: 3.3
     :attr:`tm_gmtoff` and :attr:`tm_zone` attributes are available on platforms
     with C library supporting the corresponding fields in ``struct

i.e., tm_gmtoff, tm_zone may be absent on some platforms.

How is it similar to *del datetime.timezone* if whether or not the
attributes are available depends on platform?

I don't see how any system without a historical timezone database may
support the attributes and as far as I know C library that is used by
python.exe does not use the tz database on Windows.

[1] https://docs.python.org/3.4/library/time.html#time.struct_time

To make sure that we are talking about the same thing. Here's how I've
temporarily disabled the attributes to perform the test. It *emulates*
platforms with one or both attributes missing:

  diff --git a/Lib/datetime.py b/Lib/datetime.py
  --- a/Lib/datetime.py
  +++ b/Lib/datetime.py
  @@ -1507,6 +1507,7 @@
               local = datetime(*localtm[:6])
                   # Extract TZ data if available
  +                raise AttributeError
                   gmtoff = localtm.tm_gmtoff
                   zone = localtm.tm_zone
               except AttributeError:
  @@ -2129,7 +2130,7 @@
   # pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
  -    from _datetime import *
  +    from __datetime import *
   except ImportError:

1st line forces AttributeError exception handler to execute.
2nd line disables C code that looks identical to the pure Python code.

And here's the code from the except AttributeError clause above that
I've shown in earlier messages [2] (C code does the same [3]):

  # Compute UTC offset and compare with the value implied
  # by tm_isdst.  If the values match, use the zone name
  # implied by tm_isdst.
  delta = local - datetime(*_time.gmtime(ts)[:6])
  dst = _time.daylight and localtm.tm_isdst > 0
  gmtoff = -(_time.altzone if dst else _time.timezone)
  if delta == timedelta(seconds=gmtoff):
      tz = timezone(delta, _time.tzname[dst])
      tz = timezone(delta)

note: as the example with datetime(2013, 10, 28,
tzinfo=timezone.utc).astimezone().strftime('%Z%z') in TZ=Europe/Moscow
demonstrates, this code [4] does not find the correct tz.tzname() and
therefore it is not an appropriate replacement for *tm_zone*.

The code [4] can't be fixed without data from the tz database.

[2] https://mail.python.org/pipermail/datetime-sig/2015-August/000471.html
[3] https://github.com/python/cpython/blob/fced0e12fc510e4a6158628695774ccfd02395d3/Modules/_datetimemodule.c#L4721-L4735
[4] https://github.com/python/cpython/blob/fced0e12fc510e4a6158628695774ccfd02395d3/Lib/datetime.py#L1513-L1522

More information about the Datetime-SIG mailing list