From d220466440f46d4cf3543fbe4b5d4bcb579b5dcf Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Sat, 22 Apr 2023 19:19:28 +0200 Subject: [PATCH] Backport PR #52841 on branch 2.0.x (BUG: dt.round with equal/higher freq resolution would not noop) (#52846) Backport PR #52841: BUG: dt.round with equal/higher freq resolution would not noop Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> --- doc/source/whatsnew/v2.0.1.rst | 1 + pandas/core/arrays/datetimelike.py | 8 ++++++-- pandas/tests/series/accessors/test_dt_accessor.py | 11 +++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v2.0.1.rst b/doc/source/whatsnew/v2.0.1.rst index 09074b3fe613d..d340b034b6c2c 100644 --- a/doc/source/whatsnew/v2.0.1.rst +++ b/doc/source/whatsnew/v2.0.1.rst @@ -27,6 +27,7 @@ Bug fixes ~~~~~~~~~ - Bug in :attr:`Series.dt.days` that would overflow ``int32`` number of days (:issue:`52391`) - Bug in :class:`arrays.DatetimeArray` constructor returning an incorrect unit when passed a non-nanosecond numpy datetime array (:issue:`52555`) +- Bug in :func:`Series.dt.round` when passing a ``freq`` of equal or higher resolution compared to the :class:`Series` would raise a ``ZeroDivisionError`` (:issue:`52761`) - Bug in :func:`Series.median` with :class:`ArrowDtype` returning an approximate median (:issue:`52679`) - Bug in :func:`api.interchange.from_dataframe` was unnecessarily raising on categorical dtypes (:issue:`49889`) - Bug in :func:`api.interchange.from_dataframe` was unnecessarily raising on large string dtypes (:issue:`52795`) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 976262a0f1573..843e9be6de14a 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -2005,8 +2005,12 @@ def _round(self, freq, mode, ambiguous, nonexistent): values = self.view("i8") values = cast(np.ndarray, values) - nanos = to_offset(freq).nanos # raises on non-fixed frequencies - nanos = delta_to_nanoseconds(to_offset(freq), self._creso) + offset = to_offset(freq) + offset.nanos # raises on non-fixed frequencies + nanos = delta_to_nanoseconds(offset, self._creso) + if nanos == 0: + # GH 52761 + return self result_i8 = round_nsint64(values, mode, nanos) result = self._maybe_mask_results(result_i8, fill_value=iNaT) result = result.view(self._ndarray.dtype) diff --git a/pandas/tests/series/accessors/test_dt_accessor.py b/pandas/tests/series/accessors/test_dt_accessor.py index 1123eddcdbc57..74371830f3a19 100644 --- a/pandas/tests/series/accessors/test_dt_accessor.py +++ b/pandas/tests/series/accessors/test_dt_accessor.py @@ -381,6 +381,17 @@ def test_dt_round_tz_nonexistent(self, method, ts_str, freq): with pytest.raises(pytz.NonExistentTimeError, match="2018-03-11 02:00:00"): getattr(ser.dt, method)(freq, nonexistent="raise") + @pytest.mark.parametrize("freq", ["ns", "U", "1000U"]) + def test_dt_round_nonnano_higher_resolution_no_op(self, freq): + # GH 52761 + ser = Series( + ["2020-05-31 08:00:00", "2000-12-31 04:00:05", "1800-03-14 07:30:20"], + dtype="datetime64[ms]", + ) + expected = ser.copy() + result = ser.dt.round(freq) + tm.assert_series_equal(result, expected) + def test_dt_namespace_accessor_categorical(self): # GH 19468 dti = DatetimeIndex(["20171111", "20181212"]).repeat(2)