[Python-Dev] Status on PEP-431 Timezones

ISAAC J SCHWABACHER ischwabacher at wisc.edu
Sat Jul 25 20:44:33 CEST 2015

> From: Tim Peters <tim.peters at gmail.com>
> Sent: Friday, July 24, 2015 20:39
> Cc: Alexander Belopolsky; Lennart Regebro; Python-Dev
> Subject: Re: [Python-Dev] Status on PEP-431 Timezones
> [ISAAC J SCHWABACHER <ischwabacher at wisc.edu>]
> > ...
> > I disagree with the view Tim had of time zones when he wrote that comment
> > (and that code). It sounds like he views US/Eastern and US/Central as time
> > zones (which they are), but thinks of the various America/Indiana zones as
> > switching back and forth between them, rather than being time zones in their
> > own right
> You can think of them anyway you like.  The point of the code was to
> provide a simple & efficient way to convert from UTC to local time in
> all "time zones" in known actual use at the time; the point of the
> comment was to explain the limitations of the code.  Although, as
> Allexander noted, the stated assumptions are stronger than needed.
> > I think the right perspective is that a time zone *is* the function that its
> > `fromutc()` method implements,
> Fine by me ;-)

My issue is that you're computing `fromutc()`, which is a function, in terms of `dst()` and `utcoffset()`, which aren't. I think this is backwards; `dst()` and `utcoffset()` should be computed from `fromutc()` plus some additional information that has to be present anyway in order to implement `fromutc()`. With the extra bit, `dst()` and `utcoffset()` become partial functions, which makes it *possible* to get the right answer in all cases, but it's still simpler to start with the total function and work from there.

> > although of course we need additional information in order to actually
> > compute (rather than merely mathematically define) its inverse. Daylight Saving
> > Time is a red herring,
> Overstated.  DST is in fact the _only_ real complication in 99.99% of
> time zones (perhaps even 99.9913% ;-) ).  As the docs say, if you have
> some crazy-ass time zone in mind, fine, that's why fromutc() was
> exposed (so your; crazy-ass tzinfo class can override it).

I stand by what I meant by this, even if I did a bad job of expressing the point. Assuming that all time zone discontinuities are due to DST changes breaks many time zones (really almost all of the Olson time zones, though only for a vanishingly small fraction of datetimes), but that's not the point I was making. The point is that it doesn't buy us anything. Though this is probably obscured by all the markup, the more general algorithm I gave is also simpler than the one in the comment in datetime.py, and the reason for that is that it solves an easier problem, but one that serves our practical purposes just as well.

> > and assumptions 2 and 4
> Nitpick:  4 is a consequence of 2, not an independent assumption.
> > in that exposition are just wrong from this point of view.
> As above, there is no particular POV in this code:  just a specific
> fromutc() implementation, comments that explain its limitations, and
> an invitation in the docs to override it if it's not enough for your
> case.

I went too far in inferring your viewpoint from your code.  I don't find fault with the explanation on its own terms. But adding zoneinfo to the stdlib, as PEP 431 proposes to do, requires making weaker assumptions and asking a different question than the one answered in the comment. 

> > In the worst case, Asia/Riyadh's two years of solar time completely shatter
> > these assumptions.
> Sure.  But, honestly, who cares?  Riyadh Solar Time was so
> off-the-wall that even the Saudis gave up on it 25 years ago (after a
> miserable 3-year experiment with it).  "Practicality beats purity".

As a mathematician at heart, I have a deep and abiding conviction, which I expect nobody else to share, that purity begets practicality in the long run. At least if you've found the right abstraction.

> > [eliding a more-general view of what time zones "really" are]

[note for people just joining this conversation: I think the information in the elision is critical to understanding what I'm talking about]

> I'm not eliding it because I disagree with it, but because time zones
> are political constructions.  "The math" we make up may or may not be
> good enough to deal with all future political abominations; for
> example:
> > ...
> > This assumption would be violated if, for example, some jurisdiction
> > decided to fall back two hours by falling back one hour and then
> > immediately falling back a second hour.  I recommend the overthrow
> > of any such jurisdiction and its (annexation by the Netherlands)[3].
> That's not objectively any more bizarre than Riyadh Solar Time.
> Although, if I've lived longer than you, I may be more wary about the
> creative stupidity of political schemes ;-)

It's not, you have, and you probably are. :)

But these assumptions didn't come out of nowhere. They're the assumptions behind zoneinfo, weakened as much as possible without making the problem any harder. It's hard to weaken them further and still have anything to work with. (See? I *do* still have a sense of practicality!)

Nobody wants to read me discussing this at great length, but I'll say that I don't expect any legislative body to have the collective mathematical sophistication necessary to violate piecewise continuity or computability. If you really want to troll me, I invite you to take over a government and institute a time zone based on the (Weierstrass function)[1].

> > ... (Lennart, I think this third assumption is the important part of your "no
> > changes within 48 hours of each other" assumption,
> The "48 hours" bit came from Alexander.  I'm personally unclear on
> what Lennart's problems are.


> > ...
> > All of these computations can be accomplished by searches of ordered lists
> > and applications of $fromlocal_i$.
> Do you have real-world use cases in mind beyond supporting
> long-abandoned Riyadh Solar time?

Parts of five US states (Alaska, North Dakota, Indiana, Kentucky and Michigan) have changed their standard time since 1970. But I'll admit that mentioning Riyadh was a low blow.

> > ...
> > With this perspective, arithmetic becomes "translate to UTC, operate, translate
> > back", which is as it should be.
> There _was_ a POV in the datetime design about that:  no, that's not
> how it should be.  Blame Guido ;-)  If I add, say, 24 hours to noon
> today, I want to get noon tomorrow, and couldn't care less whether DST
> started or stopped (or any other political adjustment was made) in
> between.  For that reason, it was wholly intentional that datetime +
> timedelta treats datetime as "naive".  If that's not what someone
> wants, fine, but then they don't want Python's datetime arithmetic
> BTW, there's no implication that they're "wrong" for wanting something
> different; what would be wrong is insisting that datetime's POV is
> "wrong".  Both views are valid and useful, depending on the needs of
> the application.  One had to picked as the built-in behavior, and
> "naive" won.

Sigh. This offends my sensibilities so much, but I've said my bit on this elsewhere on this list, and I don't think I have the right abstraction to cut this Gordian knot.  Point conceded.

> > ...
> > But IIUC what Lennart is complaining about
> I don't, and I wish he would be more explicit about what "the
> problem(s)" is(are).
> > is the fact that the DST flag isn't part of and can't be embedded into a local time,
> > so it's impossible to fold the second parameter to $fromlocal$ into $t$.  Without
> > that, a local time isn't rich enough to designate a single point in time and the
> > whole edifice breaks.
> You can blame Guido for that too ;-) , but in this case I disagree(d)
> with him:  Guido was overly (IMO) annoyed by that the only apparent
> purpose for a struct tm's tm_ isdst flag was to disambiguate local
> times in a relative handful of cases.  His thought:  an entire bit
> just for that?!  My thought:  get over it, it's one measly bit.

I could have sworn that the last thing I saw Guido post about the previous point was something along the lines of "oops", but I bet it was really about this.


[1]: https://en.wikipedia.org/wiki/Weierstrass_function

More information about the Python-Dev mailing list