Skip to content
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ Datetimelike
- Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` returning ``False`` on double-digit frequencies (:issue:`58523`)
- Bug in :meth:`DatetimeIndex.union` and :meth:`DatetimeIndex.intersection` when ``unit`` was non-nanosecond (:issue:`59036`)
- Bug in :meth:`Series.dt.microsecond` producing incorrect results for pyarrow backed :class:`Series`. (:issue:`59154`)
- Bug in :meth:`_validate_inferred_freq` where DateTimeIndex incorrectly raised a ``ValueError`` when assigning a logically equivalent frequency (:issue:`61086`)
- Bug in :meth:`to_datetime` not respecting dayfirst if an uncommon date string was passed. (:issue:`58859`)
- Bug in :meth:`to_datetime` on float array with missing values throwing ``FloatingPointError`` (:issue:`58419`)
- Bug in :meth:`to_datetime` on float32 df with year, month, day etc. columns leads to precision issues and incorrect result. (:issue:`60506`)
Expand Down
29 changes: 26 additions & 3 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -2519,15 +2519,38 @@ def _validate_inferred_freq(
-------
freq : DateOffset or None
"""

if inferred_freq is not None:
if freq is not None and freq != inferred_freq:
if freq is not None:
offset1, offset2 = to_offset(freq), to_offset(inferred_freq)
if type(offset1) == type(offset2):
if hasattr(offset1, "startingMonth") and hasattr(
offset2, "startingMonth"
):
if (offset1.startingMonth - offset2.startingMonth) % 3 != 0:
raise ValueError(
f"Inferred frequency {inferred_freq} from passed "
"values does not conform to passed frequency "
f"{freq.freqstr}"
)
return freq
if (
hasattr(offset1, "n")
and hasattr(offset2, "n")
and offset1.n != offset2.n
):
raise ValueError(
f"Inferred frequency {inferred_freq} from passed "
"values does not conform to passed frequency "
f"{freq.freqstr}"
)
return freq
raise ValueError(
f"Inferred frequency {inferred_freq} from passed "
"values does not conform to passed frequency "
f"{freq.freqstr}"
)
if freq is None:
freq = inferred_freq
freq = inferred_freq

return freq

Expand Down
16 changes: 16 additions & 0 deletions pandas/tests/indexes/datetimes/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,3 +1204,19 @@ def test_dti_constructor_object_dtype_dayfirst_yearfirst_with_tz(self):
result2 = DatetimeIndex([val], tz="US/Pacific", yearfirst=True)
expected2 = DatetimeIndex([yfirst]).as_unit("s")
tm.assert_index_equal(result2, expected2)

def test_validate_inferred_freq_equivalence(self):
idx = date_range("2022-02-01", freq="QS-FEB", periods=4)

new_idx = DatetimeIndex(idx, freq="QS-MAY")
assert isinstance(new_idx, DatetimeIndex)

msg = (
"Inferred frequency .* from passed "
"values does not conform to passed frequency .*"
)
with pytest.raises(
ValueError,
match=msg,
):
DatetimeIndex(idx, freq="QS-MAR")
Loading