From 5dc83c690e5ccb177c8f38738487ad81bca572f3 Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Tue, 12 Aug 2025 22:58:37 +0530 Subject: [PATCH] BUG: TimedeltaIndex.shift() infers freq when possible (GH#62094) --- pandas/core/arrays/datetimelike.py | 27 +++++-------------- .../indexes/timedeltas/test_arithmetic.py | 9 +++++++ 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 7e57b40e42430..85fcb3e348df6 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -1070,26 +1070,13 @@ def _get_arithmetic_result_freq(self, other) -> BaseOffset | None: elif isinstance(self.freq, Tick): # In these cases return self.freq - elif self.dtype.kind == "m" and isinstance(other, Timedelta): - return self.freq - elif ( - self.dtype.kind == "m" - and isinstance(other, Timestamp) - and (other.tz is None or timezones.is_utc(other.tz)) - ): - # e.g. test_td64arr_add_sub_datetimelike_scalar tdarr + timestamp - # gives a DatetimeArray. As long as the timestamp has no timezone - # or UTC, the result can retain a Day freq. - return self.freq - elif ( - lib.is_np_dtype(self.dtype, "M") - and isinstance(self.freq, Day) - and isinstance(other, Timedelta) - ): - # e.g. TestTimedelta64ArithmeticUnsorted::test_timedelta - # Day is unambiguously 24h - return self.freq - + # If no explicit freq, use inferred_freq when the index is regular + elif self.freq is None: + inferred = self.inferred_freq + if inferred is not None: + offset = to_offset(inferred) + if isinstance(offset, Tick): + return offset return None @final diff --git a/pandas/tests/indexes/timedeltas/test_arithmetic.py b/pandas/tests/indexes/timedeltas/test_arithmetic.py index a431e10dc18ab..4896fb41b7192 100644 --- a/pandas/tests/indexes/timedeltas/test_arithmetic.py +++ b/pandas/tests/indexes/timedeltas/test_arithmetic.py @@ -2,6 +2,7 @@ # Other cases can be shared in tests.arithmetic.test_timedelta64 import numpy as np +import pandas as pd from pandas import ( NaT, Timedelta, @@ -49,3 +50,11 @@ def test_tdi_division(self, index_or_series): [31 * 86400, 31 * 86400, 31 * 86400 + 5 * 60 + 3, np.nan] ) tm.assert_equal(result, expected) + + def test_timedeltaindex_shift_infers_freq(self): + # GH#62094: TimedeltaIndex.shift() should work if freq can be inferred + ind = pd.date_range("1/1/2021", "1/5/2021") - pd.Timestamp("1/3/2019") + shifted = ind.shift(1) + expected = ind + Timedelta(days=1) + tm.assert_index_equal(shifted, expected) + assert shifted.freq == pd.tseries.frequencies.to_offset("D")