Pre-Pre-PEP: The datetime.timedeltacal class
Peter J. Holzer
hjp-python at hjp.at
Sun Apr 17 04:15:54 EDT 2022
On 2022-04-17 06:08:54 +1000, Chris Angelico wrote:
> On Sun, 17 Apr 2022 at 03:37, Peter J. Holzer <hjp-python at hjp.at> wrote:
> > 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).
>
> I think Troll still only has days that consist of 23-25 hours; the
> weird part is that they move their clocks forward for Oslo's summer,
> which is their winter.
According to Wikipedia they switch between UTC+2 and UTC+0, so the
switchover days would be 22 and 26 hours, respectively.
> > 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.
>
> It sounds like you're planning for annual DST changes, but what about
> other shifts? What about when a location adopts standard time, which
> could change their UTC offset (yes, I'm aware that most places adopted
> standard time before UTC was a thing, but we still usually call it a
> UTC offset rather than messing with GMT-UTC changeover) by an
> arbitrary amount, even minutes?
Yes, I think you are right. I first thought it wouldn't matter because
you'd have to look it up in the database anyway, but that's a
non-sequitur. Clearly, when you cities switched from local times to
timezones, one hour had to be longer or shorter than 3600 seconds.
Similarily if India decided to switch to a whole-hour offset, then they
would have one hour of 30 or 90 minutes.
> It might be cleaner to simply have all of the arguments that datetime
> has: year, month, day, hour, minute, second, microsecond (with the
> possibility of merging second/usec into a single float).
Yup.
> > 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)]
>
> Quick test in Pike:
[...]
> Subtracting seventeen days from today gets us to the 31st of March,
> and adding one month to that gives us the 30th of April. Subtracting
> eighteen days gets us to the 30th of March, and adding a month to that
> _also_ gives us the 30th of April.
Same for PostgreSQL.
> > 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.
>
> Here's the local DST switchover:
[results I expected]
> > 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.
>
> By "in general", do you mean "there will be some odd exceptions", or
> "this is usually going to be unequal"?
The former.
> For instance, going back to the month boundary case, since it's not
> possible for "add one month" from two different dates to give the same
> result, obviously subtracting a month from that result can't give both
> the originals. But for the most part, I would expect t + d - d to be
> equal to t, modulo rounding error and possible DST corrections.
> Crossing a DST boundary shouldn't break this pattern; only landing in
> the actual gap/fold should cause issues.
> Is that the intention?
Yes, exactly.
> > 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]
> >
>
> Isn't that the exact same thing as saying that t + d - d == t?
No, because the overflow handling isn't reversible. Using the semantics
from Pike or Postgres:
2022-03-31 + 1 month == 2022-04-30.
But 2022-04-30 - 1 month == 2022-03-30.
If "spill over" extra days (IIRC, PHP does that but I'd have to check)
2022-03-31 + 1 month == 2022-05-01
2022-05-01 - 1 month == 2022-04-01
So t + d - d is not always == t. (If you fix this special case you'll
break some more common cases).
But I think (but haven't yet proven) that for any pair of datetimes t0
and t1 there should always exist at least one delta d such that t0 + d
== t1.
2022-03-31 + 30 days = 2022-04-30
2022-03-30 + 1 month = 2022-04-30
2022-03-31 + 31 days == 2022-05-01
2022-03-31 + 1 month + 1 day == 2022-05-01
2022-03-31 + 2 months - 30 days == 2022-05-01
Not sure which of the last three should be the canonical one. I can
make an argument for each of them.
> Or are you saying that, when you subtract two timestamps, you can
> never get one of the odd exceptions that would cause problems? Because
> I'd believe that; the net result would be that u+(t-u) == t, but
> u+((t+d)-(u+d)) might not equal t. Putting it another way: Shift
> invariance should *normally* hold, but there may be some exceptions at
> month ends (basically rounding error when you add/subtract a month)
> and DST switches.
Yes.
> When the time comes, if you need a hand putting together a PEP, feel
> free to reach out to me.
Thanks.
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/20220417/58d77008/attachment.sig>
More information about the Python-list
mailing list