From 9b65f18f1029cbc4560ab0224a5e73099e085cf9 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Sat, 1 Nov 2025 22:55:55 +0000 Subject: [PATCH] BUG: Series.resample failing for non-nanosecond unit that's out of bounds for nano reso --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/_libs/tslibs/offsets.pyx | 17 +++++++++++++---- pandas/tests/resample/test_datetime_index.py | 11 +++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 12f522301e121..1927f47382c02 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -1180,6 +1180,7 @@ Groupby/resample/rolling - Bug in :meth:`Rolling.apply` for ``method="table"`` where column order was not being respected due to the columns getting sorted by default. (:issue:`59666`) - Bug in :meth:`Rolling.apply` where the applied function could be called on fewer than ``min_period`` periods if ``method="table"``. (:issue:`58868`) - Bug in :meth:`Series.resample` could raise when the date range ended shortly before a non-existent time. (:issue:`58380`) +- Bug in :meth:`Series.resample` raising error when resampling non-nanosecond resolutions out of bounds for nanosecond precision (:issue:`57427`) Reshaping ^^^^^^^^^ diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 8fb5e739d3a4e..be86118a2b9e2 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -5688,18 +5688,27 @@ def shift_month(stamp: datetime, months: int, day_opt: object = None) -> datetim cdef: int year, month, day int days_in_month, dy + npy_datetimestruct dts + + if isinstance(stamp, _Timestamp): + creso = (<_Timestamp>stamp)._creso + val = (<_Timestamp>stamp)._value + pandas_datetime_to_datetimestruct(val, creso, &dts) + else: + # Plain datetime/date + pydate_to_dtstruct(stamp, &dts) - dy = (stamp.month + months) // 12 - month = (stamp.month + months) % 12 + dy = (dts.month + months) // 12 + month = (dts.month + months) % 12 if month == 0: month = 12 dy -= 1 - year = stamp.year + dy + year = dts.year + dy if day_opt is None: days_in_month = get_days_in_month(year, month) - day = min(stamp.day, days_in_month) + day = min(dts.day, days_in_month) elif day_opt == "start": day = 1 elif day_opt == "end": diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py index ab88d221864c0..3cd7f6c336956 100644 --- a/pandas/tests/resample/test_datetime_index.py +++ b/pandas/tests/resample/test_datetime_index.py @@ -2171,6 +2171,17 @@ def test_arrow_timestamp_resample_keep_index_name(): tm.assert_series_equal(result, expected) +def test_resample_unit_second_large_years(): + # GH#57427 + index = DatetimeIndex( + date_range(start=Timestamp("1950-01-01"), periods=10, freq="1000YS", unit="s") + ) + ser = Series(1, index=index) + result = ser.resample("2000YS").sum() + expected = Series(2, index=index[::2]) + tm.assert_series_equal(result, expected) + + @pytest.mark.parametrize("freq", ["1A", "2A-MAR"]) def test_resample_A_raises(freq): msg = f"Invalid frequency: {freq[1:]}"