[Python-Dev] PEP 495 Was: PEP 498: Literal String Interpolation is ready for pronouncement

Alexander Belopolsky alexander.belopolsky at gmail.com
Sat Sep 12 02:40:44 CEST 2015


On Fri, Sep 11, 2015 at 6:45 PM, Terry Reedy <tjreedy at udel.edu> wrote:

>
>> I think we nailed the hard issues there.   The next update will have a
>> restored hash invariant and == that satisfies all three axioms of
>> equivalency.
>>
>
> You are trying to sanely deal with politically mandated insanity.
> I think it essential that you not introduce mathematical insanity, but
> whatever you do will be less than completely satisfactory.


The insanity I am dealing with now is specific to Python datetime which
wisely blocks any binary operation that involves naive and aware datetimes,
but allows comparisons and subtractions of datetimes with different
timezones.  This is not an unusual situation given a limited supply of
binary operators, Python has to reuse them in less than ideal ways. For
example,

>>> a = 'a'
>>> b = 'b'
>>> c = 5
>>> (a + b) * c == a * c + b * c
False

is less than ideal if you hold the distributive law of arithmetic sacred.
Similarly, '-' is reused in datetime for two different operation: if s and
t are datetimes with the same tzinfo, s - t tells you how far to move hands
on the local clock to arrive at s when you start at t.  This is clearly a
very useful operation that forms the basis of everything else that we do in
datetime.  Note that for this operation, it does not matter what kind of
time your clock is showing or whether it is running at all.  We are not
asking how long one needs to wait to see s after t was shown.  We are just
asking how far to turn the knob on the back of the clock.  This operation
does not make sense when s and t have different tzinfos, so in this case a
'-' is reused for a different operation.  This operation is much more
involved.  We require an existence of some universal time (UTC) and a rule
to convert s and t to that time and define s - t as s.astimezone(UTC) -
t.timezone(UTC).  In the later expression '-' is taken in the "turns of the
knob" sense because the operands are in the same timezone (UTC).

Clearly, when we "abuse" the mathematical notation in this way, we cannot
expect mathematical identities to hold and it is easy to find for example,
aware datetimes u, t, and s such that (t - u) - (s - u) ≠ t - s.

Deciding when it is ok to sacrifice mathematical purity for practical
convenience is an art, not a science.  The case of interzone datetime
arithmetic is a borderline case.  I would much rather let users decide what
they want: s.astimezone(t.tzinfo) - t, s - t.astimezone(s.tzinfo) or
 s.astimezone(UTC) - t.astimezone(UTC) and not assume that s - t "clearly"
means the last of the three choices.  But the decision to allow interzone t
- s was made long time ago and it is a PEP 495 goal to change that.


>
>  I am not making a better progress because I am debating
>> with myself about the fate of < and > comparisons.
>>
>
> Both should not be true for the same pair ;-)


I'll give you that.  No worries.

>
>
> > Cross-zone
>
>> comparisons strike in full force there as well because two times ordered
>> in UTC may appear in the opposite order in the local timezone where the
>> clock is moved back.
>>
>
> Comparison of absolute Newtonion time, represented by UTC, and local
> 'clock face' relative time with political hacks, are different concepts.
> If I get up at 8:00 AM (in Delaware, USA) and you get up at 8:01 wherever
> you are, which of us got up earlier?  It depends on what 'earlier' means
> in the context and purpose of the question. Are we asking about wakeup
> discipline, or email exchange?
>

There is no "earlier" or "later".  There are "lesser" and "greater" which
are already defined for all pairs of aware datetimes.  PEP 495 doubles the
set of possible datetimes and they don't fit in one straight line anymore.
The whole point of PEP 495 is to introduce a "fold" in the timeline.


> Pick whichever you and whoever consider to be most useful.  Presuming that
> one can convert to UTC before comparision, I suspect the local version.


It is more delicate than that.  Are you willing to accept a possibility of
an infinite loop if you run a binary search for a UTC time in an ordered
list of local times?  We tolerate that with numbers, but you only have this
risk when you have a "nan" in your list.  I don't think the new PEP 495
datetimes will be nearly as bad as floating point NaNs: at least datetime
== will still be reflexive and transitive unlike  floating point ==.  Still
I am not ready to say that we have solved all the puzzles yet.  But we are
close.


>
>  Note that I saved the hash invariant and the
>> transitivity of == at the expense of the loss of trichotomy in
>> comparisons (we will have pairs of aware datetimes that are neither
>> equal nor < nor >).
>>
>
> That is the nature of partial orders.


Yes, but are we willing to accept that datetimes have only partial order?
And in Python 3 we consider comparison between unorderable objects to be an
error instead of silently returning False.  I am strongly against allowing
exceptions in astimezone(), ==, or hash()

>
>
>  I don't think we need to change anything with < and
>>  > comparisons,
>>
>
> I am guessing that the comparisons are currently local.


Yes, they are for naive datetime pairs and pairs with items sharing
tzinfo.  The problem is what to do with the interzone comparisons.


>
>
> but I am trying to come up with the arguments that will
>> at least be convincing to myself.  (I suspect that if I am not the only
>> one who worries about this, the other such people can be counted by the
>> values of the fold flag. :-)
>>
>
> Good luck ;-)


Thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20150911/569fbd4c/attachment.html>


More information about the Python-Dev mailing list