Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: date comparison fails when series is all pd.NaT values #61188 #61200

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
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 @@ -660,6 +660,7 @@ Datetimelike
- Bug in :meth:`to_datetime` reports incorrect index in case of any failure scenario. (:issue:`58298`)
- Bug in :meth:`to_datetime` wrongly converts when ``arg`` is a ``np.datetime64`` object with unit of ``ps``. (:issue:`60341`)
- Bug in setting scalar values with mismatched resolution into arrays with non-nanosecond ``datetime64``, ``timedelta64`` or :class:`DatetimeTZDtype` incorrectly truncating those scalars (:issue:`56410`)
- Bug in :attr:`Series.dt.date` where Series with all NaT values would raise an error when compared to a datetime.date (:issue:`61188`)

Timedelta
^^^^^^^^^
Expand Down
47 changes: 47 additions & 0 deletions pandas/core/indexes/accessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,53 @@ def freq(self):
'2YS-JAN'
"""
return self._get_values().inferred_freq

@property
def date(self):
"""
Return the date component (year, month, day) of each datetime in the Series.

This property returns a Series of Python datetime.date objects corresponding to
the date portion of each datetime64[ns] value in the Series. For missing values
(NaT), the result will be NaT.

Returns
-------
Series
A Series of datetime.date objects or NaT, with dtype object.

Notes
-----
- The result is always returned with object dtype.
- This ensures comparisons with Python datetime.date values (e.g. using <=)
work even when the Series contains only missing values (NaT).

Examples
--------
>>> s = pd.Series(pd.to_datetime(["2020-01-01", pd.NaT]))
>>> s.dt.date
0 2020-01-01
1 NaT
dtype: object

>>> s.dt.date <= datetime.date(2024, 1, 1)
0 True
1 False
dtype: bool
"""

from pandas import Series
import datetime

values = self._get_values()
as_dates = values.to_pydatetime()

def extract_date(x):
return x.date() if isinstance(x, datetime.datetime) else pd.NaT

result = [extract_date(v) for v in as_dates]

return Series(result, index=self._parent.index, name=self._parent.name, dtype=object).__finalize__(self._parent)

def isocalendar(self) -> DataFrame:
"""
Expand Down
18 changes: 18 additions & 0 deletions pandas/tests/series/indexing/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,21 @@ def test_compare_datetime_with_all_none():
result = ser > ser2
expected = Series([False, False])
tm.assert_series_equal(result, expected)

def test_dt_date_dtype_all_nat_is_object():
# Ensure .dt.date on all-NaT Series returns object dtype and not datetime64
# GH#61188
s = pd.Series([pd.NaT, pd.NaT])
s = pd.to_datetime(s)
result = s.dt.date
assert result.dtype == object
assert result.isna().all()

def test_dt_date_all_nat_le_date():
#All-NaT Series should not raise error when compared to a datetime.date
# GH#61188
s = pd.Series([pd.NaT, pd.NaT])
s = pd.to_datetime(s)
result = s.dt.date <= datetime.now().date()
expected = pd.Series([False, False])
tm.assert_series_equal(result, expected)
Loading