[Datetime-SIG] PEP-431/495

Carl Meyer carl at oddbird.net
Mon Aug 24 20:30:31 CEST 2015

On 08/24/2015 12:02 PM, Guido van Rossum wrote:
> Maybe the underlying reason is that to me, even a datetime with tzinfo
> does not refer to an instant -- it refers to something that's displayed
> on a clock. To me, arithmetic is a way of moving the hands of the clock.

Yes, I think that's the basis of the differing views here.

Clocks don't show timezones, so if I just wanted to "move the hands of
the clock," I'd use a naive datetime, which is the proper representation
for "something that is displayed on the clock."

A datetime with a tzinfo _does_ correspond to an instant (even if you
don't want to think of it that way), so to some of us it is confusing if
it occasionally behaves as if it does not.

>     In other words, he just assumed that timeline arithmetic was his only
>     reasonable option as the author of a useful, non-buggy tzinfo
>     implementation. As a user of pytz, it was certainly what I expected, and
>     I'd have considered "classic arithmetic" to be a bug (thanks to pytz, I
>     avoided even knowing that was Python's default behavior until this
>     thread), so I can't fault his assumption.
> But again that proves nothing. Of course if you're used to pytz's
> behavior you'll find the other behavior buggy. And it still does nothing
> to explain (to me) why the two need to be inextricably linked.

It was the behavior I expected when I _first picked up_ pytz, and if I
hadn't gotten it from pytz, I'd have -- well, I'd have continued to do
store datetimes internally in UTC and do arithmetic in UTC, which is
what I do and recommend to others. But I'd have considered the
possibility of naive arithmetic with aware datetimes as an unnecessary
attractive nuisance and bug magnet.

>     I think the other linkage between the two is that pytz's "every tzinfo
>     instance is fixed-offset" is the most natural way to solve the PEP-495
>     problem in the absence of PEP 495 and ensure that all datetime instances
>     are unambiguous and valid.
> Again (as can be seen from the endless bickering between Alexander and
> myself about whether this is a bug or not) your view is colored by
> pytz's position.

I think the argument about whether it's a bug has been unenlightening,
because it of course depends on what you want (and how you see
datetimes, as described above). I certainly think that pytz's need for
`normalize()` calls is most unfortunate (and I know Stuart agrees with
that). But it preserves the most important thing (from my perspective),
which is that the resulting datetime always corresponds to the right
instant, even if it's got the offset wrong until you normalize it. Given
the limited options Stuart had, I think that was the best choice
available for my use cases (and apparently his).

>     Faced with "I need to store this extra
>     disambiguation bit in the tzinfo somehow, to clarify which of two
>     offsets is intended when a timezone transitions from one offset to
>     another", you can either store a boolean somewhere which is usually
>     irrelevant and very hard to name sensibly, or you can "store" the flag
>     by simply assigning a tzinfo instance which represents the specific
>     offset you want (but also knows its full timezone rules, so it can
>     "normalize" to a different offset when asked to).
> But almost all instants (99.98%, according to Alexander) are not
> ambiguous and have no need for the disambiguation.

Of course. But that can easily be an argument in favor of pytz's
implementation choice. Why give every tzinfo a boolean flag that is
worse-than-useless (because its presence and naming is confusing) in the
99.98% of cases when it's not needed, when you can instead give every
tzinfo an unambiguous offset and eliminate the problem?

 If I every program an
> alarm to occur weekday at 7am I'd be most disturbed if an implementation
> botched the DST transition and woke me up at 6am one Monday morning. And
> yet that 7am is in a specific timezone (mine!).

This example is meaningless, because "program an alarm to occur every
weekday at 7am" is not a valid use case for any type of datetime
duration arithmetic at all. It's a use case for a period recurrence,
which is an entirely different beast (e.g. dateutil.rrule). It's the
same type of operation as "notify me every second Saturday," not as
"what will the time be in 15 seconds".

Programming that use case using "add 86400 seconds to the time my alarm
went off yesterday" is certainly a possible newbie mistake someone might
make who hasn't worked with timezones or DST before (and who also forgot
the "weekdays only" requirement), but it's a mistake that should be
fixed by pointing them to a recurrence library, not by having aware
datetimes use naive arithmetic.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://mail.python.org/pipermail/datetime-sig/attachments/20150824/137b81d3/attachment-0001.sig>

More information about the Datetime-SIG mailing list