Skip to content

Commit d85e9a2

Browse files
authored
BUG: Timedelta drops decimals if precision is greater than nanoseconds (#36771)
1 parent b422aab commit d85e9a2

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

doc/source/whatsnew/v1.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ Timedelta
521521
- Bug in :class:`TimedeltaIndex`, :class:`Series`, and :class:`DataFrame` floor-division with ``timedelta64`` dtypes and ``NaT`` in the denominator (:issue:`35529`)
522522
- Bug in parsing of ISO 8601 durations in :class:`Timedelta`, :meth:`pd.to_datetime` (:issue:`37159`, fixes :issue:`29773` and :issue:`36204`)
523523
- Bug in :func:`to_timedelta` with a read-only array incorrectly raising (:issue:`34857`)
524+
- Bug in :class:`Timedelta` incorrectly truncating to sub-second portion of a string input when it has precision higher than nanoseconds (:issue:`36738`)
524525

525526
Timezones
526527
^^^^^^^^^

pandas/_libs/tslibs/timedeltas.pyx

+7-2
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,11 @@ cdef inline int64_t parse_timedelta_string(str ts) except? -1:
405405
m = 10**(3 -len(frac)) * 1000 * 1000
406406
elif len(frac) > 3 and len(frac) <= 6:
407407
m = 10**(6 -len(frac)) * 1000
408-
else:
408+
elif len(frac) > 6 and len(frac) <= 9:
409409
m = 10**(9 -len(frac))
410-
410+
else:
411+
m = 1
412+
frac = frac[:9]
411413
r = <int64_t>int(''.join(frac)) * m
412414
result += timedelta_as_neg(r, neg)
413415

@@ -1143,6 +1145,9 @@ class Timedelta(_Timedelta):
11431145
Notes
11441146
-----
11451147
The ``.value`` attribute is always in ns.
1148+
1149+
If the precision is higher than nanoseconds, the precision of the duration is
1150+
truncated to nanoseconds.
11461151
"""
11471152

11481153
def __new__(cls, object value=_no_input, unit=None, **kwargs):

pandas/core/tools/timedeltas.py

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ def to_timedelta(arg, unit=None, errors="raise"):
6666
to_datetime : Convert argument to datetime.
6767
convert_dtypes : Convert dtypes.
6868
69+
Notes
70+
-----
71+
If the precision is higher than nanoseconds, the precision of the duration is
72+
truncated to nanoseconds for string inputs.
73+
6974
Examples
7075
--------
7176
Parsing a single string to a Timedelta:

pandas/tests/tools/test_to_timedelta.py

+17
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,20 @@ def test_to_timedelta_nullable_int64_dtype(self):
210210
result = to_timedelta(Series([1, None], dtype="Int64"), unit="days")
211211

212212
tm.assert_series_equal(result, expected)
213+
214+
@pytest.mark.parametrize(
215+
("input", "expected"),
216+
[
217+
("8:53:08.71800000001", "8:53:08.718"),
218+
("8:53:08.718001", "8:53:08.718001"),
219+
("8:53:08.7180000001", "8:53:08.7180000001"),
220+
("-8:53:08.71800000001", "-8:53:08.718"),
221+
("8:53:08.7180000089", "8:53:08.718000008"),
222+
],
223+
)
224+
@pytest.mark.parametrize("func", [pd.Timedelta, pd.to_timedelta])
225+
def test_to_timedelta_precision_over_nanos(self, input, expected, func):
226+
# GH: 36738
227+
expected = pd.Timedelta(expected)
228+
result = func(input)
229+
assert result == expected

0 commit comments

Comments
 (0)