[Datetime-SIG] PEP-431/495

Stuart Bishop stuart at stuartbishop.net
Thu Aug 27 13:13:37 CEST 2015

On 27 August 2015 at 08:37, Tim Peters <tim.peters at gmail.com> wrote:

> I don't know whether Stuart mucked with arithmetic because he believed
> that was necessary in order to get conversions to work correctly (if
> so, he was mistaken), or whether the effects on arithmetic were just a
> _consequence_ of using fixed-offset classes all the time (that's "a
> natural" outcome of using only fixed-offset classes - it would take
> extra effort to _stop_ it - classic and timeline arithmetic are the
> same thing in any eternally-fixed-offset timezone) .  He said, in an
> earlier message, that conversion was his primary concern.  But maybe
> we're all using the same words with different meanings.

The fixed-offset classes and sorting arithmetic were the only way to
get things round tripping. Take a datetime. Convert it to another
timezone. Add one hour to both. Compare. The results were
inconsistent. You would only get correct results with fixed offset
timezones, because the builtin arithmetic ignored the timezone,
because there was no is_dst flag and without it it is impossible to
get correct results. The burden was left on tzinfo implementations to
deal with the problem. You could have naive times and do arithmetic
correctly, or you could have zone aware times and do conversions
correctly, but to do both developers had to always convert to and from
utc to do the arithmetic. And developers being lazy creatures wouldn't
bother because it would normally work, or even always work in their
particular timezone, and systems would crash at 4am killing innocent
kittens. And this was a problem with my tzinfo implementation, because
the only way you could possibly experience the problem was by using my
tzinfo implementation. Python had avoided this clearly documented
problem by not supplying any tzinfo implementations, even though it
would have been easy to create a 'local' one using the information
already exposed in the time module, and I'd always assumed that fixing
it was a requirement of adding timezone implementations to the
standard library. So I fixed it. Drunk on my own cleverness and
relative youth, it never occurred to me that it was possible to
rationalize the existing behaviour with a straight face, where after
going to all the effort of constructing and adding a tzinfo to your
datetime it would sit there entirely ignored by Python, except for
conversion operations, consistently giving you answers that are
demonstrably incorrect using most modern timekeeping systems. I'm
still not capable of conjuring up such a monumental rationalization ;)

>>> My hope was that 495 alone would at least spare pytz's users from
>>> needing to do a `.normalize()` dance after `.astimezone()` anymore.
>>> Although I'm not clear on why it's needed even now.
>> As far as I know, normalize() is not necessary after astimezone() even
>> now
>> https://answers.launchpad.net/pytz/+question/249229
> That agrees with my best guess, but my knowledge of pytz is shallow.
> If it's correct that the .normalize() dance isn't needed here, it
> would be nice if Stuart plainly said so on that page, and - of course
> - changed the docs to stop saying it _is_ required.  And then it's
> also the case that I don't see any benefit to pytz from PEP 495 alone.
> :-(

Yeah, I'm putting off answering that one because I'm not sure if I'll
get the answer right. People sometimes think I actually know what I'm
doing. I'll have a look after I get the overdue pytz release out.

>> replace() is just a shortcut for a constructor.
> Yet pytz does nothing to check .replace() results, right?

It has no opportunity to check the results at the moment, nor does it
have the opportunity to swap in the correct fixed offset tzinfo. It
just gets rudely shoved into a datetime instance without consent. So
replace gives you what it gives you, and you have to sort it out with
a call to normalize, at which point you realize you have a timezone
definition from 1910 in play and learn to always construct your
localized datetime instances with tzinfo.localize(). Such a lovely
user experience.

Stuart Bishop <stuart at stuartbishop.net>

More information about the Datetime-SIG mailing list