BUG: Timedelta components rounded by float imprecision · Issue #31354 · pandas-dev/pandas (original) (raw)

Problem description

It appears that there is some premature rounding happening in the Timedelta constructor that makes it so the unit-adjusted sums of the days, seconds, microseconds and nanoseconds attributes do not sum to the total number of nanoseconds. A fundamental assumption of the datetime.timedelta type (and breaking this assumption breaks Liskov substitutability) is that the total time difference at the precision of microseconds can be represented by summing up the unit-adjusted days, seconds and microseconds attributes, and it's how datetime.total_seconds() works.

I believe that this is the root cause of issue #31043, which was "fixed" with what is essentially a workaround in PR #31155, as I mentioned in this comment.

At the moment the most obvious effect is that bug #31043 only is fixed for recent versions of dateutil, but presumably it will show up in other places where standard datetime arithmetic is being used on pandas timestamps.

Code Sample, a copy-pastable example if possible

def to_ns(td): ns = td.days * 86400 ns += td.seconds ns *= 1000000 ns += td.microseconds ns *= 1000 ns += td.nanoseconds return ns

td = timedelta(1552211999999999872, unit="ns") print(td.value) # 1552211999999999872 print(to_ns(td)) # 1552212000000000872

Actual output:

1552211999999999872
1552212000000000872

Expected output

1552211999999999872
1552211999999999872