[Python-Dev] Status on PEP-431 Timezones

Tim Peters tim.peters at gmail.com
Tue Jul 28 06:26:01 CEST 2015


[Paul Moore]
>>>

[Tim]
>> Guido will never allow any aspect of "leap seconds" into the core,

[Chris Barker <chris.barker at noaa.gov]
> really? that is a shame (and odd) -- it's a trick, because we don't know
> what leap seconds will be needed in the future, but other than that, it's
> not really any different than leap years,

It couldn't be _more_ different in three key respects:

1) The leap year rules are algorithmic, while leap seconds are added
at unpredictable times by decree.  That means any attempt to support
them across dozens of platforms also needs to find a way to distribute
& synchronize leap-second info across all the platforms too, over &
over & over again.  Few want to volunteer for yet another never-ending
new task.

2) Leap years visibly effect everyone on the planet who uses a
calendar.  Leap seconds don't.  To the contrary, civil authorities do
all they can to keep leap seconds "out of sight, out of mind".

3) If adding leap seconds had any visible semantic effect in Python,
99.99% of Python users would complain about being bothered with them.
In contrast, removing leap-year support would cause 32.6% of Python
users to complain -  eventually ;-)

> ...
> But leap seconds are the big red herring -- darn few people need them!

Do you?  If not, put your energy instead into something you _do_ need
;-)  But if you do need them, write a patch and try to sneak it by
Guido.

> It's pretty rare, indeed, to be expressing your time in gregorian dates, and also
> care about accuracy down to the seconds over centuries....

Python's datetime supports microsecond precision.  Mere seconds are
for wimps ;-)

...

>>> 5. The problems all arise *only* with timezones whose UTC offset
>>> varies depending on the actual time (e.g., timezones that include the
>>> transition to DST and back).

> which is a good reason to "store" your datetime in UTC, and do all the math
> there.

As mentioned earlier, uniform patterns in local time can be -
typically because of DST transitions - "lumpy" in UTC.  Like "every
Friday at 3pm in time zone T" is trivial to deal with _in_ T using
"naive" datetime arithmetic, but the corresponding datetimes in UTC
are irregular (the number of hours between successive corresponding
UTC times can slobber around between 167 and 169)..  There are no
one-size-fits-all solutions here.

....

>> It ignores the possibility called #3 above (that some bureaucrat
>> changed the name of a fixed-offset time zone despite that the offset
>> didn't change).

> Should the code ever care about a time zone's name? it seems that two tzinfo
> objects should only be considered the same if they ar the same instance.
> period. so not sure what the real issue is with (3)

_Users_ care.  That's why the tzname() method exists.  When they
display it, it's at best confusing if the name they see doesn't match
the name they expect.

But I'm not sure _how_ the name can get out of synch.  Upon
reflection, the specific case I had in mind was actually caused by
incorrect coding of a tzinfo subclass.  Maybe that's the only way a
wrong name can be returned (apart from incorrect names in the base
zoneinfo data files).


>>> 2. Arithmetic within a complex timezone. Theoretically, this is simple
>>> enough (convert to UTC, do the calculation naively, and convert back).
>>> But in practice, that approach doesn't always match user expectations.

> what reasonable expectation does this not match?

The "every Friday at 3pm in time zone T" example comes to mind:
trying to do _that_ arithmetic in UTC is an irregular mess.

More generally, as mentioned before, the current fromutc()
implementation can't deal reliably with a time zone changing its
standard UTC offset (if it isn't clear, fromutc() is used in
astimezone(), which latter is used for time zone conversions).

Paul, do you have something else in mind for this one?


> ...
> " this time the next day" -- that could be 23, 24, or 25 hours, if you are
> bridging a DST transition -- but that kind of operation should not be in the
> stdlib -- unless, of course, an entire "work with calendar time" lib is
> added -- but that's a whole other story.
>
> for a datetime.timedelta -- a day is 24 hours is a day. period, always.

But in "naive time", the difference between 3pm one day and 3pm the
next day is also always 24 hours, period, always.

> So you can compute "one day from now", which is the same as "24 hours from
> now" or 1440 minutes from now, or ...., but you can't compute "this time
> tomorrow" -- not with a timedelta, anyway.

To the contrary, for a dozen years "+ timedelta(days=1)" HAS computed
"this time tomorrow", and exactly the same as "+ timedelta(hours=24)".
  Those have never done anything other in Python.


>> Python picked one to make dead easy
>> ("naive"), and intended to make the other _possible_ via longer-winded
>> (but conceptually straightforward) code.

> exactly -- you can extract the year, month, day -- add one to the day, and
> then go back. But then you'll need to do all the "30 days hath September"
> stuff - and leap years, and ...

It sounds like you believe Python made the choice it didn't make:  It
made the "same time tomorrow" choice.  The conceptually
straightforward way to implement the other choice is to convert to
UTC, do arithmetic in UTC, then convert back to the original time
zone.  Or, better when it applies, stick to UTC all the time, only
converting to some other time zone for display purposes (if needed at
all).

>>>  datetime gave us
>>> a richer timedelta object and hence has extra problems.

> it's only a little richer, and doesn't really add problems, just doesn't
> solve some common problems...

Indeed, all timedelta really does is represent an integer number of
microseconds, with a bunch of ways in the constructor to spare the
user from having to remember how to convert from other duration units.
That's just, in effect, syntactic sugar.  Under the covers it's just a
big integer (spelled in a weird mixed-radix system).


>> There's more to it than that.  "Naive time" also wants, e.g.,
>> "01:45:00 tomorrow minus 01:45:00 today" to return 24 hours.  Maybe
>> the same thing in disguise, though.

> I think so -- but it's not a "problem" because the datetime module doesn't
> have any way to express "tomorrow" anyway.

See above.  Expressing "tomorrow" _is_ built in.  Ditto "same time in
N weeks", "one hour beyond the same time 113 days earlier", etc.

> ... even with complex time zones. I don't
> think timedelta evey needs to know about timezones at all. timedelta, is
> actually really, really simple, all it needs to know is how to translate
> various units into its internal representation (days, seconds, microseconds
> ?)

timedelta indeed knows nothing about time zones.  People who hate
Python's "naive single-zone arithmetic" should realize that's entirely
about how datetime's arithmetic operators are implemented, nothing
about how timedelta is implemented.


More information about the Python-Dev mailing list