diff --git a/doc/source/whatsnew/v1.0.1.rst b/doc/source/whatsnew/v1.0.1.rst index 206be97fe202f..e300574e87341 100644 --- a/doc/source/whatsnew/v1.0.1.rst +++ b/doc/source/whatsnew/v1.0.1.rst @@ -67,6 +67,8 @@ Interval Indexing ^^^^^^^^ + +- Fixed regression when indexing a ``Series`` or ``DataFrame`` indexed by ``DatetimeIndex`` with a slice containg a :class:`datetime.date` (:issue:`31501`) - Fixed regression in :class:`DataFrame` setting values with a slice (e.g. ``df[-4:] = 1``) indexing by label instead of position (:issue:`31469`) - - diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 2b4636155111f..416c3d0701a85 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -1,4 +1,4 @@ -from datetime import datetime, time, timedelta, tzinfo +from datetime import date, datetime, time, timedelta, tzinfo import operator from typing import Optional import warnings @@ -758,6 +758,13 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): if isinstance(start, time) or isinstance(end, time): raise KeyError("Cannot mix time and non-time slice keys") + # Pandas supports slicing with dates, treated as datetimes at midnight. + # https://github.com/pandas-dev/pandas/issues/31501 + if isinstance(start, date) and not isinstance(start, datetime): + start = datetime.combine(start, time(0, 0)) + if isinstance(end, date) and not isinstance(end, datetime): + end = datetime.combine(end, time(0, 0)) + try: return Index.slice_indexer(self, start, end, step, kind=kind) except KeyError: diff --git a/pandas/tests/indexing/test_datetime.py b/pandas/tests/indexing/test_datetime.py index 42f992339f036..c8c2d1ed587cf 100644 --- a/pandas/tests/indexing/test_datetime.py +++ b/pandas/tests/indexing/test_datetime.py @@ -1,4 +1,4 @@ -from datetime import datetime, timedelta +from datetime import date, datetime, timedelta from dateutil import tz import numpy as np @@ -350,3 +350,23 @@ def test_loc_label_slicing(self): expected = ser.iloc[:-1] tm.assert_series_equal(result, expected) + + @pytest.mark.parametrize( + "slice_, positions", + [ + [slice(date(2018, 1, 1), None), [0, 1, 2]], + [slice(date(2019, 1, 2), None), [2]], + [slice(date(2020, 1, 1), None), []], + [slice(None, date(2020, 1, 1)), [0, 1, 2]], + [slice(None, date(2019, 1, 1)), [0]], + ], + ) + def test_getitem_slice_date(self, slice_, positions): + # https://github.com/pandas-dev/pandas/issues/31501 + s = pd.Series( + [0, 1, 2], + pd.DatetimeIndex(["2019-01-01", "2019-01-01T06:00:00", "2019-01-02"]), + ) + result = s[slice_] + expected = s.take(positions) + tm.assert_series_equal(result, expected)