Pre-Pre-PEP: The datetime.timedeltacal class

Peter J. Holzer hjp-python at hjp.at
Sat Apr 16 13:35:51 EDT 2022


I intend to take this to python-ideas, but I'm not currently subscribed
there and I think I should probably do a bit of research before
proposing something over there. So I'll start by gathering some feedback
here with a rough sketch.

Datetime arithmetic in the real world is typically not done in seconds,
but in calendaric units: Hours, days, weeks, months, years, ...
The problem is that several of these have varying lengths:

* 1 minute may be 60 or 61 seconds (theoretically also 59, but that
  hasn't happened yet).
* 1 day can be 23, 24 or 25 hours (unless you are in Troll, Antarctica,
  where it's even weirder).
* 1 month may be 28, 29, 30 or 31 days (let's stick to the Gregorian
  calendar)

The standard library has a datetime.timedelta class which does store
days and seconds separately, so somebody seems to have had the right
idea, but the normalization rules make it impossible to distinguish
between "1 day plus 1 hour" and "25 hours", and it doesn't deal with
months at all.

Technically it shouldn't be too hard to "fix" timedelta, but that
wouldn't be backward compatible and would very likely break existing
code.

Therefore a new class (provisionally called timedeltacal, because it is
calendaric, not absolute) should be added to datetime:

Internally it stores months, days, seconds and microseconds as ints.

The seconds and microseconds split is mostly for compatibility with
datetime and timedelta. We could store seconds as a float instead.

We don't store minutes since leap seconds aren't usually represented in
"computer time", so they are unlikely to be useful in a timedeltacal
object.

Days are stored since they aren't a fixed multiple of any smaller unit.
Months are stored since they aren't a fixed multiple of any smaller unit.

Hours, weeks and years aren't stored since they are always 60 minutes, 7
days and 12 months respectively.

When adding a timedeltacal object to a datetime, the fields are added
from most to least significant: First a new date is computed by
advancing the number of months specified [TODO: Research how other
systems handle overflow (e.g. 2022-01-31 + 1 month: 2022-02-31 doesn't
exist)], then advance the number of days. Finally add the number of
seconds and microseconds, taking into accout daylight savings time
switches if the datetime is time zone aware.

Subtracting a timedeltacal object from a datetime is the same, just in
the opposite direction.

Note that t + d - d is in general not equal to t.

We can't cnange the semantics of datetime - datetime, so there must be a
function to compute the difference between to datetimes as a
timedeltacal. It could be a method on datetime (maybe t.sub(u) for t-u
like in Go) or a constructor which takes two datetime objects.

In any case I think that u + (t - u) == t should hold. [TODO: Check that
this is possible]

        hp

-- 
   _  | Peter J. Holzer    | Story must make more sense than reality.
|_|_) |                    |
| |   | hjp at hjp.at         |    -- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |       challenge!"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://mail.python.org/pipermail/python-list/attachments/20220416/61153aae/attachment.sig>


More information about the Python-list mailing list