Skip to content

Commit 16ca7d9

Browse files
authored
BUG: Timedelta.round() raises ZeroDivisionError when internal unit is 's' and target frequency is sub-second (#64836)
1 parent f937e71 commit 16ca7d9

3 files changed

Lines changed: 23 additions & 6 deletions

File tree

doc/source/whatsnew/v3.1.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ Timedelta
213213
^^^^^^^^^
214214
- Bug in :class:`DateOffset` where ``DateOffset(1)`` and ``DateOffset(days=1)`` returned different results near daylight saving time transitions (:issue:`61862`)
215215
- Bug in :func:`to_timedelta` where passing ``np.str_`` objects would fail in Cython string parsing (:issue:`48974`)
216-
-
216+
- Fixed regression in :meth:`Timedelta.round`, :meth:`Timedelta.floor`, and :meth:`Timedelta.ceil` raising ``ZeroDivisionError`` for sub-second ``freq`` (:issue:`64828`)
217217

218218
Timezones
219219
^^^^^^^^^

pandas/_libs/tslibs/timedeltas.pyx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ from cpython.object cimport (
1818
PyObject_RichCompare,
1919
)
2020

21+
from pandas._libs.tslibs.offsets cimport to_offset
22+
2123
import numpy as np
2224

2325
cimport numpy as cnp
@@ -2355,17 +2357,24 @@ class Timedelta(_Timedelta):
23552357
@cython.cdivision(True)
23562358
def _round(self, freq, mode):
23572359
cdef:
2358-
int64_t result, unit
2360+
int64_t result, nanos
23592361
ndarray[int64_t] arr
2360-
2361-
unit = get_unit_for_round(freq, self._creso)
2362+
freq_arg = freq
2363+
freq = to_offset(freq, is_period=False)
2364+
nanos = get_unit_for_round(freq, self._creso)
2365+
if nanos == 0:
2366+
if freq.nanos == 0:
2367+
raise ValueError("Division by zero in rounding")
2368+
2369+
# e.g. self.unit == "s" and sub-second freq
2370+
return self
23622371

23632372
arr = np.array([self._value], dtype="i8")
23642373
try:
2365-
result = round_nsint64(arr, mode, unit)[0]
2374+
result = round_nsint64(arr, mode, nanos)[0]
23662375
except OverflowError as err:
23672376
raise OutOfBoundsTimedelta(
2368-
f"Cannot round {self} to freq={freq} without overflow"
2377+
f"Cannot round {self} to freq={freq_arg} without overflow"
23692378
) from err
23702379
return Timedelta._from_value_and_reso(result, self._creso)
23712380

pandas/tests/scalar/timedelta/methods/test_round.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,11 @@ def test_round_non_nano(self, unit):
185185
res = td.ceil("min")
186186
assert res == Timedelta("1 days 02:35:00")
187187
assert res._creso == td._creso
188+
189+
def test_round_freq_finer_than_resolution(self):
190+
# GH#64828
191+
td = Timedelta(1.0, unit="days").as_unit("s")
192+
assert td.unit == "s"
193+
assert td.round("100ms") == Timedelta("1 days 00:00:00")
194+
assert td.floor("100ms") == Timedelta("1 days 00:00:00")
195+
assert td.ceil("100ms") == Timedelta("1 days 00:00:00")

0 commit comments

Comments
 (0)