diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index f43d13bf25e9d..cb0827a9fadd3 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -666,6 +666,7 @@ Other Deprecations - Deprecated using ``epoch`` date format in :meth:`DataFrame.to_json` and :meth:`Series.to_json`, use ``iso`` instead. (:issue:`57063`) - Deprecated allowing ``fill_value`` that cannot be held in the original dtype (excepting NA values for integer and bool dtypes) in :meth:`Series.unstack` and :meth:`DataFrame.unstack` (:issue:`12189`, :issue:`53868`) - Deprecated allowing ``fill_value`` that cannot be held in the original dtype (excepting NA values for integer and bool dtypes) in :meth:`Series.shift` and :meth:`DataFrame.shift` (:issue:`53802`) +- Deprecated slicing on a :class:`Series` or :class:`DataFrame` with a :class:`DatetimeIndex` using a ``datetime.date`` object, explicitly cast to :class:`Timestamp` instead (:issue:`35830`) .. --------------------------------------------------------------------------- .. _whatsnew_300.prior_deprecations: diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 606961970b177..f64152278a648 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -26,11 +26,13 @@ to_offset, ) from pandas._libs.tslibs.offsets import prefix_mapping +from pandas.errors import Pandas4Warning from pandas.util._decorators import ( cache_readonly, doc, set_module, ) +from pandas.util._exceptions import find_stack_level from pandas.core.dtypes.common import is_scalar from pandas.core.dtypes.dtypes import ( @@ -645,6 +647,13 @@ def _maybe_cast_slice_bound(self, label, side: str): # Pandas supports slicing with dates, treated as datetimes at midnight. # https://github.com/pandas-dev/pandas/issues/31501 label = Timestamp(label).to_pydatetime() + warnings.warn( + # GH#35830 deprecate last remaining inconsistent date treatment + "Slicing with a datetime.date object is deprecated. " + "Explicitly cast to Timestamp instead.", + Pandas4Warning, + stacklevel=find_stack_level(), + ) label = super()._maybe_cast_slice_bound(label, side) self._data._assert_tzawareness_compat(label) diff --git a/pandas/tests/indexes/datetimes/test_indexing.py b/pandas/tests/indexes/datetimes/test_indexing.py index 5877a38bbee11..742e3439db723 100644 --- a/pandas/tests/indexes/datetimes/test_indexing.py +++ b/pandas/tests/indexes/datetimes/test_indexing.py @@ -10,6 +10,7 @@ from pandas._libs import index as libindex from pandas.compat.numpy import np_long +from pandas.errors import Pandas4Warning import pandas.util._test_decorators as td import pandas as pd @@ -654,13 +655,16 @@ def test_get_slice_bounds_datetime_within( index = bdate_range("2000-01-03", "2000-02-11").tz_localize(tz) key = box(year=2000, month=1, day=7) - if tz is not None: - with pytest.raises(TypeError, match="Cannot compare tz-naive"): - # GH#36148 we require tzawareness-compat as of 2.0 - index.get_slice_bound(key, side=side) - else: - result = index.get_slice_bound(key, side=side) - assert result == expected + warn = None if box is not date else Pandas4Warning + msg = "Slicing with a datetime.date object is deprecated" + with tm.assert_produces_warning(warn, match=msg): + if tz is not None: + with pytest.raises(TypeError, match="Cannot compare tz-naive"): + # GH#36148 we require tzawareness-compat as of 2.0 + index.get_slice_bound(key, side=side) + else: + result = index.get_slice_bound(key, side=side) + assert result == expected @pytest.mark.parametrize("box", [datetime, Timestamp]) @pytest.mark.parametrize("side", ["left", "right"]) diff --git a/pandas/tests/series/indexing/test_getitem.py b/pandas/tests/series/indexing/test_getitem.py index 8ba5e8452711d..37d6c9b42e003 100644 --- a/pandas/tests/series/indexing/test_getitem.py +++ b/pandas/tests/series/indexing/test_getitem.py @@ -16,6 +16,7 @@ timezones, ) from pandas.compat.numpy import np_version_gt2 +from pandas.errors import Pandas4Warning from pandas.core.dtypes.common import is_scalar @@ -314,7 +315,9 @@ def test_getitem_slice_date(self, slc, positions): [0, 1, 2], DatetimeIndex(["2019-01-01", "2019-01-01T06:00:00", "2019-01-02"]), ) - result = ser[slc] + msg = "Slicing with a datetime.date object is deprecated" + with tm.assert_produces_warning(Pandas4Warning, match=msg): + result = ser[slc] expected = ser.take(positions) tm.assert_series_equal(result, expected)