Skip to content

Commit 73eb6dd

Browse files
committed
BUG: Timedelta.round() raises ZeroDivisionError when internal unit is 's' and target frequency is sub-second (pandas-dev#64836)
(cherry picked from commit 16ca7d9)
1 parent 648c250 commit 73eb6dd

3 files changed

Lines changed: 23 additions & 5 deletions

File tree

doc/source/whatsnew/v3.0.3.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Fixed regressions
2020
Bug fixes
2121
^^^^^^^^^
2222
- Fixed regression in :func:`pandas.bdate_range` where specifying ``end`` on a weekend with ``periods`` returned fewer dates than expected (:issue:`64834`)
23+
- Fixed regression in :meth:`Timedelta.round`, :meth:`Timedelta.floor`, and :meth:`Timedelta.ceil` raising ``ZeroDivisionError`` for sub-second ``freq`` (:issue:`64828`)
2324

2425
.. ---------------------------------------------------------------------------
2526
.. _whatsnew_303.contributors:

pandas/_libs/tslibs/timedeltas.pyx

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

20+
from pandas._libs.tslibs.offsets cimport to_offset
21+
2022
import numpy as np
2123

2224
cimport numpy as cnp
@@ -2321,17 +2323,24 @@ class Timedelta(_Timedelta):
23212323
@cython.cdivision(True)
23222324
def _round(self, freq, mode):
23232325
cdef:
2324-
int64_t result, unit
2326+
int64_t result, nanos
23252327
ndarray[int64_t] arr
2326-
2327-
unit = get_unit_for_round(freq, self._creso)
2328+
freq_arg = freq
2329+
freq = to_offset(freq, is_period=False)
2330+
nanos = get_unit_for_round(freq, self._creso)
2331+
if nanos == 0:
2332+
if freq.nanos == 0:
2333+
raise ValueError("Division by zero in rounding")
2334+
2335+
# e.g. self.unit == "s" and sub-second freq
2336+
return self
23282337

23292338
arr = np.array([self._value], dtype="i8")
23302339
try:
2331-
result = round_nsint64(arr, mode, unit)[0]
2340+
result = round_nsint64(arr, mode, nanos)[0]
23322341
except OverflowError as err:
23332342
raise OutOfBoundsTimedelta(
2334-
f"Cannot round {self} to freq={freq} without overflow"
2343+
f"Cannot round {self} to freq={freq_arg} without overflow"
23352344
) from err
23362345
return Timedelta._from_value_and_reso(result, self._creso)
23372346

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)