[Datetime-SIG] Adding PEP 495 support to dateutil

Akira Li 4kir4.1i at gmail.com
Fri Sep 18 22:59:50 CEST 2015

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

> On Fri, Sep 18, 2015 at 2:42 PM, Tim Peters <tim.peters at gmail.com> wrote:
>> When converting from UTC to a local ambiguous time, you obviously know
>> which UTC time you started with.  The problem is that it's impossible
>> to _record_ which UTC time you started with.  The date and time
>> attributes of the local datetimes are (must be) identical, so the only
>> way you _could_ record it is by overriding .fromutc() to attach a
>> different tzinfo object (the only bits of a datetime object that could
>> possibly differ between the earlier and later of an ambiguous local
>> time).
>> Which is what pytz does.
> The pytz hack is in violation of the strict reading of the reference manual
> [1] which says "The purpose of fromutc() is to adjust the date and time
> data ...".  I think it is in the spirit if not in the letter of datetime
> module design that fromutc(dt) should not change dt.tzinfo.

pytz's fromutc() returns the correct* result. dateutil can't do it (at
the moment) https://github.com/dateutil/dateutil/issues/112

* The word "correct" here does not depend on the programming language
  specification and/or its implementation e.g. from the bug description:

    Input: 2011-11-06 05:30:00 UTC+0000, America/Toronto
    Expected: 2011-11-06 01:30:00 EDT-0400

If the reference manual mandates a different result then it is wrong wrong.

> In any case, I think we have concluded on this list that pytz approach is
> not an example to be followed.  I just wanted to mention for Paul's benefit
> that it is not just the arithmetic that is affected by the pytz hack.  The
> changes in arithmetic are themselves consequences of the violation of the
> "fromutc(dt).tzinfo is dt.tzinfo" invariant.

Consider the following (natural) equality:

  tz.fromutc(utc_time) == utc_time.replace(tzinfo=utc_tz).astimezone(tz)

The right side allows *utc_time.tzinfo* being None or *utc_time.tzinfo*
may be some equivalent of *timezone.utc*. It is confusing that the
method named *fromutc()* (its stdlib implementation) rejects *utc_time*
if it is in utc timezone.

stdlib's behavior that mandates utc_time.tzinfo == tz where tz may have
non-zero utc offset is weird (mind-bending -- input time must be utc but
tzinfo is not utc -- wtf). There is no need to attach *tz* before calling
*tz.fromutc()* -- tz is passed as *self* anyway.

> [1]: https://docs.python.org/3/library/datetime.html#datetime.tzinfo.fromutc

More information about the Datetime-SIG mailing list