[Datetime-SIG] PEP-0500 (Alternative datetime arithmetic) Was: PEP 495 ... is ready ...

Chris Barker chris.barker at noaa.gov
Wed Aug 19 19:23:11 CEST 2015


IIUC, PEP 500 essentially says essentially anything that datetime does can
be delegated to a tzinfo object. Which reduces the datetime object to a
simple container of a datetime stamp:

years, months, days, hours, min, sec, microsec.

As the current implementation has a way to add on tzinfo object, it is a
way forward to make them all-powerful, to add arbitrary functionality
without changing the way an existing code will work -- but it it the only
or best way?


I think it would be very helpful (maybe only to me) to spell out the goals
of PEP 500, so we can determine if they are goals we want to support, and
if PEP 500 is the best way to support them:


I see a number of different goals, all crammed in:

 - Support different Calendars : anything other than Proleptic Gregorian
Calendar -- maybe include Lunar Calendars, etc???

 - Support leap-seconds - this strikes me as essentially a slightly
different Calendar -- aside from having to use an updated database, it's
very similar to leap years.

 - Support different time arithmetic -- "Duration" and "Period" arithmetic
-- or "strict", or ????

I think it's a fine idea to open the door to support all these, but is PEP
500 the way to do it?

Anything else?

We now have a few particular objects to work with:

time
date
datetime
timedelta
tzinfo

These each have their own purpose and protocol  -- can we leverage that to
support the above?

*tzinfo* essentially provides the offset to/from UTC time for a given
timezone at a given datetime. PEP 495 adds a feature that completes the
ability to fully support  this functionality -- why not keep that clean?

*timedelta* is essentially a way to encode a time duration -- microseconds.
Useful and simple.

*datetime* encodes a timestamp, and provides an implementation of the
proleptic gregorian calendar, so that it can convert differences between
datetimes to "real" timespans -- i.e. timedeltas. Thus is can support
subtracting datetimes, and adding timedeltas to a datetime.

OK -- so given all this (and Tim, please correct me where I have it wrong,
-- I probably do), how best to support the goals above? (and, of course not
break any existing code)

**Arithmetic:**

We've identified two "kinds" of arithmetic -- 'Duration' -- actual seconds,
and "Period", timestamps are important -- i.e., "the next day, same time",
etc...). Currently strict arithmetic is not supported by "aware" datetime
objects, but neither is much in the way of Period Arithmetic.

 -  *Period arithmetic*: As I understand it, this is pretty well supported
by dateutils right now -- are the datetuitls maintainers asking for
anything to make this better / easier??? Also, Period arithmetic requires
all sorts of things other than simple addition and subtraction -- "Next
Tuesday", "next business day", who knows what? so it seems overloading
__add__ and __sub__ doesn't really buy much anyway.

 - *Duration arithmetic*: I think this is the most useful thing to add --
currently, if you have tz-aware datetimes, you have to convert both to UTC,
do the math, and convert back to the timezone you want. This isn't too
painful, and is considered best practice by some folks anyway (actually,
best practice is to convert to UTC on I/O, and always use UTC internally).
But despite best practices, sometimes someone simply wants to do it in the
time zone they are in. And I suspect there is code out there that does a
simple subtraction, and it works fine if they haven't crosses a DST border,
so they haven't found the bug.

  -- so how to add Duration arithmetic? Since this is currently handled by
datetime, that seems like the obvious place to put it. Either with a
subclass, or, my preference, with a attribute that tells you want kind of
arithmetic you want, which would, of course, default to the current
behavior. The trick here is that if one were to subtract two datetimes with
the flag set differently, you'd have to decide which to respect -- but we
could document which takes precedence. And this is the same problem as when
you have two datetime with different tzinfo implementations.

  - There was talk of having multiple kinds time deltas, which might
represent either Durations or Periods, but as timedelta only supports
Periods that map precisely and unambiguously to a particular Duration, that
would be a much bigger API change to do anything useful. And probably not
be the way to go anyway, as mapping all the kinds of Period arithmetic you
want to binary operations isn't practical.

 - Also -- one could make a new datetime object that did the same thing as
the current one, but stored the timestamp as a "time_span_since_an_epoch",
to get better performance for Duration arithmetic, while sacrificing
performance for pulling out the human-readable representation. I don't know
that anyone would do that, but it would be a way to go, and I don't think
would be do-able by delegating to the tzinfo object.


** Different Calendars **
So how to handle different Calendars? -- again, the Calendar implementation
is in datetime now, so subclassing datetime makes the most sense to me. It
could be subclassed to support leap seconds, for instance, and all the rest
of  the machinery would work fine: timedeltas, time, tzinfo objects.

Also, if you want to get really far out, then lunar calendars, etc, aren't
suited to the year, month, day system currently used by datetime, so you'd
have to re-implement that anyway -- it couldn't be crammed into a tzinfo
object -- at least without a lot of pain.

And implementing a new Calendar with a new duck-typed datetime object would
require no changes to the std lib -- so nothing to argue about here :-)

So all this reduces to one maybe-proposal for the stdlib: add a flag to
datetime specifying whether you want "Duration" Arithmetic, rather than the
current "naive" arithmetic.

I know on this list at some point someone suggested that the "strict" flag
go in the tzinfo object, but I can't see why it should be there, other than
that we're messing with that object in PEP 495 already.

So, in short:

I don't think the The PEP 500 "delegate everything to tzinfo objects"
approach is the way to go. Python already has subclassing, when you want
different behaviour of an object. But in any case, if everyone else thinks
it's the way to go, then it needs an explanation for why it's better than
putting the new functionality in datetime subclasses, or duck-typed
classes. Or, for that matter, what I think Guido is suggesting -- a totally
different datetime module.

-Chris


-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/datetime-sig/attachments/20150819/58d7e5df/attachment-0001.html>


More information about the Datetime-SIG mailing list