Skip to content
Open
Show file tree
Hide file tree
Changes from all 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.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,7 @@ Datetimelike
- Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` does not raise on Custom business days frequencies bigger then "1C" (:issue:`58664`)
- 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:`DatetimeIndex.where` and :meth:`TimedeltaIndex.where` failing to set ``freq=None`` in some cases (:issue:`24555`)
- Bug in :meth:`Index.union` with a ``pyarrow`` timestamp dtype incorrectly returning ``object`` dtype (:issue:`58421`)
- Bug in :meth:`Series.dt.microsecond` producing incorrect results for pyarrow backed :class:`Series`. (:issue:`59154`)
- Bug in :meth:`Timestamp.normalize` and :meth:`DatetimeArray.normalize` returning incorrect results instead of raising on integer overflow for very small (distant past) values (:issue:`60583`)
Expand All @@ -996,7 +997,6 @@ Datetimelike
- Bug in constructing arrays with a timezone-aware :class:`ArrowDtype` from timezone-naive datetime objects incorrectly treating those as UTC times instead of wall times like :class:`DatetimeTZDtype` (:issue:`61775`)
- Bug in setting scalar values with mismatched resolution into arrays with non-nanosecond ``datetime64``, ``timedelta64`` or :class:`DatetimeTZDtype` incorrectly truncating those scalars (:issue:`56410`)


Timedelta
^^^^^^^^^
- Accuracy improvement in :meth:`Timedelta.to_pytimedelta` to round microseconds consistently for large nanosecond based Timedelta (:issue:`57841`)
Expand Down
12 changes: 9 additions & 3 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ def __getitem__(self, key: PositionalIndexer2D) -> Self | DTScalarOrNaT:
else:
# At this point we know the result is an array.
result = cast(Self, result)
result._freq = self._get_getitem_freq(key)
# error: Incompatible types in assignment (expression has type
# "BaseOffset | None", variable has type "None")
result._freq = self._get_getitem_freq(key) # type: ignore[assignment]
return result

def _get_getitem_freq(self, key) -> BaseOffset | None:
Expand Down Expand Up @@ -527,6 +529,10 @@ def view(self, dtype: Dtype | None = None) -> ArrayLike:
# are present in this file.
return super().view(dtype)

def _putmask(self, mask: npt.NDArray[np.bool_], value) -> None:
super()._putmask(mask, value)
self._freq = None # GH#24555

# ------------------------------------------------------------------
# Validation Methods
# TODO: try to de-duplicate these, ensure identical behavior
Expand Down Expand Up @@ -2042,7 +2048,7 @@ def _maybe_pin_freq(self, freq, validate_kwds: dict) -> None:
if self._freq is None:
# Set _freq directly to bypass duplicative _validate_frequency
# check.
self._freq = to_offset(self.inferred_freq)
self._freq = to_offset(self.inferred_freq) # type: ignore[assignment]
elif freq is lib.no_default:
# user did not specify anything, keep inferred freq if the original
# data had one, otherwise do nothing
Expand Down Expand Up @@ -2442,7 +2448,7 @@ def take(

if isinstance(maybe_slice, slice):
freq = self._get_getitem_freq(maybe_slice)
result._freq = freq
result._freq = freq # type: ignore[assignment]

return result

Expand Down
11 changes: 11 additions & 0 deletions pandas/tests/indexes/datetimes/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ def test_getitem_int_list(self):


class TestWhere:
@pytest.mark.parametrize("is_td", [True, False])
def test_where_freq_invalidation(self, is_td):
# GH#24555
index = date_range("20130101", periods=3, tz="US/Eastern")
if is_td:
index = index - index[0]
other = Index([pd.NaT, pd.NaT] + index[2:].tolist())

result = index.where(notna(other), other)
assert result.freq is None

def test_where_doesnt_retain_freq(self):
dti = date_range("20130101", periods=3, freq="D", name="idx")
cond = [True, True, False]
Expand Down
Loading