Arrow: Problem with differences between time points

Created on 5 Oct 2019  路  7Comments  路  Source: arrow-py/arrow

Hi,

the shift() method is nice and seems to work with localized time with some kind of "natural" semantic. However it leads to some results (related to differences between time points).
```

t0 = arrow.now().shift(weeks=3) # The day before the next DST fall transition

t0

t1 = t0.shift(days=1)

t1

t1 - t0
datetime.timedelta(1)

So far, so good. A DST transition occurs between ``t0`` and ``t1`` (I'm living in Paris) and shifting by one day keeps the same time (16:33) with UTC offset adjusted (+02:00 to +01:00). The difference is one day, expressed as a ``timedelta``.

Now, convert the dates into UTC: 

t2 = t0.to('UTC')

t2

t3 = t1.to('UTC')

t3

t2 == t0 and t3 == t1
True

t1 - t2
datetime.timedelta(1, 3600)

(t3 - t2) == (t1 - t0)
False

t0 + (t3 - t2) == t1
False
```
The problem is that, while the time points are the same in local time or UTC (which is expected), their difference is no longer the same. And a few expected invariants are no longer true.

As a conclusion,

  1. Differences between time points shall always imply a conversion to UTC, even if they are in the same time zone. At least, we would have t1 - t0 == t3 - t2 == t3 - t0 == t1 - t2. This should be clearly explained in the documentation.
  2. The documentation should explain that a difference between 2 time points lead to a "naive" delta, even if arrow enforces time zone aware time points.
  3. Time zone aware time delta could be introduced with a clean semantic (to be defined?)...

Best regards,

Antoine

bug

All 7 comments

I could implement points 1 & 2, within the next few days. Is that fine @jadchaar?

@adm271828 could you clarify exactly what you would expect to happen here instead. We're still trying to figure out whether this is an issue with arrow or timedelta.

Hi,

The very basic requirement in my example is that since 1) t0 and t2 represent the very same time point and 2) t1 and t3 represent the very same time point, then 3) we should at least have t1 - t0 represent the same time delta as t3 - t2. It shall not depend on the timezone in which the time points have their representation. But unfortunately it does...

In the example, the difference shall be 25 hours, which means, expressed as a timedelta: one day + one hour with one day being defined as exactly 24 hours (and not one day having a varying natural semantic the timedelta can not express).

Points 1 & 2 in my proposal shall be enough to deal with that in a consistent way. Enforcing both time points to be in the same time zone when we take the difference is not enough.

Next, let me try to clarify point 3. The design of arrow takes into account the fact time zones are an intrinsic component of a time point (in other words, naive time points are ambiguous since they to not identify a unique point on a universal time axis).

The point is this design rule shall be extended to time differences, in order to give consistency to calculus over time points and their differences. I would say this is a problem with timedelta that shall also carry time zone information. I can see two solutions.

First one (my points 1 & 2 in original post): use existing timedelta, but explicitly state that those na茂ve time deltas live in the UTC time zone and enforce a few constraints such as:

  • you can only obtain such time delta from time points in UTC time zone
  • you can only add a time delta to a time point in UTC time zone
  • you ask the caller to explicitly convert time points in the UTC time zone before any operation that involves such a time delta
  • it is explicitly stated that one day in a time delta means exactly 24 hours
  • relaxed constraint: a conversion to UTC is performed before but resulting time points are converted into UTC time zone
  • even more relaxed: a conversion to UTC is performed before and resulting time points are converted back to original time zone

Second one; use a custom time delta with a custom semantic, where one day would means one natural day. Then add and substract those time delta with arrow's shift semantic. Note this could yield to curious results when the delta is obtained from 2 time points with a DST transition in between (especially if one of the time points is such a day) and is added back to another time point.

Or, perhaps accept a naive timedelta as an argument to shift (with natural semantic)?

Hope this helps.

Best regards,

Antoine

I would note that changes to this behavior would mean arrows are no longer drop-in replacements for datetime, as this is a deliberate (if, in some cases, counter-intuitive) property of datetime.

See this article on datetime arithmetic for more details.

In that case we can close this as there is nothing to really fix here.

Well, I just meant the arithmetic part of it. The proposal here is not entirely clear IMO, but anything using arrow-specific methods won't affect compatibility with datetime.

There might be room for some sort of "absolute time difference" method, or custom timedelta types that encode whether or represents an absolute or calendar difference.

Also, pendulum did abandon this particular but of compatibility, so it's not entirely without precedent. I am not sure if it has caused them any problems.

I mainly wanted to clarify that arithmetic in datetime is defined in a specific way and users may be relying on that.

Yeah maybe we could implement some custom timedelta types, possibly as part of adding support for ISO 8601 durations.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andrewmwilson picture andrewmwilson  路  5Comments

LaurensBosscher picture LaurensBosscher  路  4Comments

Kirkman picture Kirkman  路  5Comments

ceorcham picture ceorcham  路  3Comments

liosha picture liosha  路  7Comments