Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v3.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ Timedelta
^^^^^^^^^
- Bug in :class:`DateOffset` where ``DateOffset(1)`` and ``DateOffset(days=1)`` returned different results near daylight saving time transitions (:issue:`61862`)
- Bug in :func:`to_timedelta` where passing ``np.str_`` objects would fail in Cython string parsing (:issue:`48974`)
-
- Fixed regression in :meth:`Timedelta.round`, :meth:`Timedelta.floor`, and :meth:`Timedelta.ceil` raising ``ZeroDivisionError`` for sub-second ``freq`` (:issue:`64828`)

Timezones
^^^^^^^^^
Expand Down
18 changes: 14 additions & 4 deletions pandas/_libs/tslibs/timedeltas.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2355,17 +2355,27 @@ class Timedelta(_Timedelta):
@cython.cdivision(True)
def _round(self, freq, mode):
cdef:
int64_t result, unit
int64_t result, nanos
ndarray[int64_t] arr

unit = get_unit_for_round(freq, self._creso)
from pandas._libs.tslibs.offsets import to_offset

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you cimport this at the top?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other than this LGTM. ping on green

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbrockmendel I moved cimport to the top. Thank you.


freq_arg = freq
freq = to_offset(freq, is_period=False)
nanos = get_unit_for_round(freq, self._creso)
if nanos == 0:
if freq.nanos == 0:
raise ValueError("Division by zero in rounding")

# e.g. self.unit == "s" and sub-second freq
return self

arr = np.array([self._value], dtype="i8")
try:
result = round_nsint64(arr, mode, unit)[0]
result = round_nsint64(arr, mode, nanos)[0]
except OverflowError as err:
raise OutOfBoundsTimedelta(
f"Cannot round {self} to freq={freq} without overflow"
f"Cannot round {self} to freq={freq_arg} without overflow"
) from err
return Timedelta._from_value_and_reso(result, self._creso)

Expand Down
8 changes: 8 additions & 0 deletions pandas/tests/scalar/timedelta/methods/test_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,11 @@ def test_round_non_nano(self, unit):
res = td.ceil("min")
assert res == Timedelta("1 days 02:35:00")
assert res._creso == td._creso

def test_round_freq_finer_than_resolution(self):
# GH#64828
td = Timedelta(1.0, unit="days").as_unit("s")
assert td.unit == "s"
assert td.round("100ms") == Timedelta("1 days 00:00:00")
assert td.floor("100ms") == Timedelta("1 days 00:00:00")
assert td.ceil("100ms") == Timedelta("1 days 00:00:00")
Loading