[Datetime-SIG] Adding PEP 495 support to dateutil

Tim Peters tim.peters at gmail.com
Sat Sep 19 03:33:48 CEST 2015


[Akira Li <4kir4.1i at gmail.com>]
> pytz's fromutc() returns the correct* result. dateutil can't do it (at
> the moment) https://github.com/dateutil/dateutil/issues/112

Do you understand why PEP 495 is being proposed?


> ...
> Consider the following (natural) equality:
>
>   tz.fromutc(utc_time) == utc_time.replace(tzinfo=utc_tz).astimezone(tz)

Clear as mud to me ;-)


> The right side allows *utc_time.tzinfo* being None or *utc_time.tzinfo*
> may be some equivalent of *timezone.utc*.

Since the RHS replaces utc_time.tzinfo before using utc_time, the RHS
"allows" utc_time.tzinfo to be anything whatsoever at the start.


> It is confusing that the method named *fromutc()* (its stdlib implementation)
> rejects *utc_time* if it is in utc timezone.

But your use, despite your claim of being "natural", is highly
_un_natural.  The natural use of .astimezone() is to invoke it _from_
a datetime object:

    a_datetime.astimezone(tz)

.fromutc() was rarely intended to be invoked directly, except perhaps
by tzinfo authors.  In that context, its real use is to help implement
.astimezone(),  And its calling conventions are natural in that
context:

    def datetime.astimezone(self, tz):
        myoffset = self.utcoffset()
        utc = (self - myoffset).replace(tzinfo=tz)
        return tz.fromutc(utc)



> stdlib's behavior that mandates utc_time.tzinfo == tz

Not "==", "is".


> 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.

Redundancy helps catch programming errors.  I know darned well this
check helped catch errors I made when implementing this stuff to begin
with.  There's always potential confusion when one object delegates
operations to operations of the same names implemented by a contained
object.

If you don't like it, tough ;-)  Stick to using astimezone() and leave
the internals alone.  If you are going to play with the internals,
follow the rules,  It's not like they weren't documented ;-)


More information about the Datetime-SIG mailing list