[Datetime-SIG] Another round on error-checking

Tim Peters tim.peters at gmail.com
Fri Sep 4 06:11:30 CEST 2015

>> I'm out of time for tonight, but will try to make more tomorrow.  Just
>> one for now, because I think it cuts to the _real_ heart of this batch
>> of messages:

> I don't think this cuts to the heart of anything :/ I think it avoids
> the main point I've made (several times) to latch instead onto a tangent
> I should have left out.

Fair enough.  I only had time for one, so latched on to the lamest one ;-)

>> That's the heart:  you simply despise classic arithmetic.

> Sorry, but no. I have nothing at all against naive arithmetic. I think
> both naive arithmetic and timeline arithmetic have good use cases.
> What I have trouble with is a tz-annotated datetime object that
> fundamentally can't decide whether it's living in a naive or timeline
> model, and thus behaves unpredictably.
> This is a problem today, but at least the behavior can be explained
> fairly simply: the model is naive when operating within the same
> timezone, and aware anytime you're converting between timezones or
> interoperating between timezones.
> PEP 495, AFAICS, makes the problem worse, because it introduces another
> bit of information that only makes sense in a timeline view. That new
> bit now allows round-tripping from UTC, which is great (no problem,
> because conversions are an area where tz-annotated datetimes already
> tried to behave as tz-aware instants in time). But then it can't quite
> decide how to rationalize that new bit of information with its naive
> internal view of time, so it settles on a mish-mash of inconsistent
> behavior that violates basic arithmetic identities we all learned in
> elementary school and only makes any sense if you've followed this
> entire thread.

Eh.  It's not perfect, but I don't know that anyone (present company
excepted) will care much.  It matters only for the later of ambiguous
times in at worst (in common zones) one hour per year, and then only
for someone using classic datetime-datetime subtraction or comparison
starting in _some_ (not all) cases in such a fold.

Perhaps this makes it wholly unusable.  I doubt most would reach that
conclusion, but it's possible.

> If you want to cut to the heart of the matter, tell me how you would
> write the documentation for how arithmetic works on a tz-annotated
> datetime post-PEP-495.

Already did in a different message ("if at least one operand has
fold=1, acts as if the tzinfos were distinct" - reduced to a prior
case).  Of course that doesn't make _sense_ in the naive time model.
Repeating that point isn't really needed ;-)

> Does it work on a naive "move the hands of the
> clock" model? (No, because I can subtract 1:30AM from 2:30AM and get "2
> hours" in some cases.);

Assuming DST is ending and moves the clock back 1 hour, then:

1. Assuming a post-495 tzinfo:

   A. If 2:30AM is the later of ambiguous times with fold=1, 2 hours.
   B. If 2:30AM is the earlier of ambiguous times with fold=0, 1 hour.
   C. If 1:30AM is the later of ambiguous times with fold=1, 1 hour.
   D. If 1:30AM is the earlier of ambiguous times with fold=0, 1 hour.
   In all other cases, 1 hour.
   In all cases, 1:30AM will compare "less than" 2:30AM..
   Note that classic arithmetic is still used if both operands have fold=0;
   so nothing _could_ change in cases B and D.
   Note that using US rules, it's 1 hour in all cases (2:30AM isn;t
   ambiguous under US rules. so A and B can't apply).  Switch to,
    e.g., 1:30AM - 12;30AM  to get an "interesting" case for US rules..

2. Assuming a pre-495 tzinfo:

   What they see will depend on what their fold-blind tzinfo makes
   up for times in a fold.  The choice recommended in the docs is
   to treat an ambiguous time as being the later.  If so, cases 1A
   & 1C still apply, and all cases return the same results.
   If the tzinfo makes the opposite choice, then case 1A returns 1
   hour and case 1C returns 2 hours.

So after 495 is implemented, they will see a difference of 2 hours in
some cases when the "real world" difference really is 2 hours, and
regardless of whether they're using a pre- or post-495 tzinfo..
That's not particularly surprising:  nobody thinks _wholly_ in "naive
time" ;-)

Of course nobody will (or should even try to) remember all those
cases.  An app that really cares (if any exist - none of my code
cares) will need to "do something" about it.  Or we'll need to add
code to ignore `fold` if a pre-495 tzinfo is in use (in which case
nothing will change if they stick to pre-495 tzinfos).

Yes, it would be better if nobody had to do anything.  No, I'm not
appalled, just mildly annoyed so far.

> Does it work on a UTC timeline model? (No, clearly not.) So what is the
> model, stated precisely and concisely?

This part isn't driven a model; it's driven by pragmatism
("practicality beats purity").  The sanest model is "it's classic
unless you're near a fold, and if you care anything about what happens
then when doing classic arithmetic you're wasting your time:  e.g.,
force it out of a fold if you need to care".

I've never written an app that needs to worry about this.  Classic
arithmetic in naive time is a simple (but highly useful) form of
"period arithmetic", and things like "same time next week" are rarely
(never, for me) concerned with hours near a transition time.  They're
usually about interacting with other people or businesses.

> And is it actually backwards-compatible with current code that converts
> from UTC to local time and then does arithmetic on those local times, or
> compares them to each other? (Not around a DST transition, no.)

You don't need any of that - the 2:30AM - 1:30AM example above already
sufficed to show it's not always backward compatible.  That's not
surprising (said before I don't think anything _useful_ to existing
code can be wholly backward compatible).

More information about the Datetime-SIG mailing list