Skip to content

Commit 90a6135

Browse files
authored
DEPR: is_all_dates (pandas-dev#36697)
1 parent 78bca00 commit 90a6135

20 files changed

+87
-41
lines changed

doc/source/whatsnew/v1.2.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ Deprecations
214214
- :meth:`DataFrame.lookup` is deprecated and will be removed in a future version, use :meth:`DataFrame.melt` and :meth:`DataFrame.loc` instead (:issue:`18682`)
215215
- The :meth:`Index.to_native_types` is deprecated. Use ``.astype(str)`` instead (:issue:`28867`)
216216
- Deprecated indexing :class:`DataFrame` rows with datetime-like strings ``df[string]``, use ``df.loc[string]`` instead (:issue:`36179`)
217+
- Deprecated casting an object-dtype index of ``datetime`` objects to :class:`DatetimeIndex` in the :class:`Series` constructor (:issue:`23598`)
218+
- Deprecated :meth:`Index.is_all_dates` (:issue:`27744`)
217219

218220
.. ---------------------------------------------------------------------------
219221

pandas/core/generic.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -9528,7 +9528,13 @@ def truncate(
95289528

95299529
# if we have a date index, convert to dates, otherwise
95309530
# treat like a slice
9531-
if ax.is_all_dates:
9531+
if ax._is_all_dates:
9532+
if is_object_dtype(ax.dtype):
9533+
warnings.warn(
9534+
"Treating object-dtype Index of date objects as DatetimeIndex "
9535+
"is deprecated, will be removed in a future version.",
9536+
FutureWarning,
9537+
)
95329538
from pandas.core.tools.datetimes import to_datetime
95339539

95349540
before = to_datetime(before)

pandas/core/indexes/base.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -2086,12 +2086,25 @@ def inferred_type(self) -> str_t:
20862086
return lib.infer_dtype(self._values, skipna=False)
20872087

20882088
@cache_readonly
2089-
def is_all_dates(self) -> bool:
2089+
def _is_all_dates(self) -> bool:
20902090
"""
20912091
Whether or not the index values only consist of dates.
20922092
"""
20932093
return is_datetime_array(ensure_object(self._values))
20942094

2095+
@cache_readonly
2096+
def is_all_dates(self):
2097+
"""
2098+
Whether or not the index values only consist of dates.
2099+
"""
2100+
warnings.warn(
2101+
"Index.is_all_dates is deprecated, will be removed in a future version. "
2102+
"check index.inferred_type instead",
2103+
FutureWarning,
2104+
stacklevel=2,
2105+
)
2106+
return self._is_all_dates
2107+
20952108
# --------------------------------------------------------------------
20962109
# Pickle Methods
20972110

pandas/core/indexes/datetimelike.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class DatetimeIndexOpsMixin(ExtensionIndex):
9898
_hasnans = hasnans # for index / array -agnostic code
9999

100100
@property
101-
def is_all_dates(self) -> bool:
101+
def _is_all_dates(self) -> bool:
102102
return True
103103

104104
# ------------------------------------------------------------------------

pandas/core/indexes/interval.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ def func(self, other, sort=sort):
10921092
# --------------------------------------------------------------------
10931093

10941094
@property
1095-
def is_all_dates(self) -> bool:
1095+
def _is_all_dates(self) -> bool:
10961096
"""
10971097
This is False even when left/right contain datetime-like objects,
10981098
as the check is done on the Interval itself

pandas/core/indexes/multi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,7 @@ def to_flat_index(self):
17331733
return Index(self._values, tupleize_cols=False)
17341734

17351735
@property
1736-
def is_all_dates(self) -> bool:
1736+
def _is_all_dates(self) -> bool:
17371737
return False
17381738

17391739
def is_lexsorted(self) -> bool:

pandas/core/indexes/numeric.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def _assert_safe_casting(cls, data, subarr):
149149
pass
150150

151151
@property
152-
def is_all_dates(self) -> bool:
152+
def _is_all_dates(self) -> bool:
153153
"""
154154
Checks that all the labels are datetime objects.
155155
"""

pandas/core/missing.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def interpolate_1d(
199199
return yvalues
200200

201201
if method == "time":
202-
if not getattr(xvalues, "is_all_dates", None):
202+
if not getattr(xvalues, "_is_all_dates", None):
203203
# if not issubclass(xvalues.dtype.type, np.datetime64):
204204
raise ValueError(
205205
"time-weighted interpolation only works "
@@ -327,7 +327,7 @@ def _interpolate_scipy_wrapper(
327327
"piecewise_polynomial": _from_derivatives,
328328
}
329329

330-
if getattr(x, "is_all_dates", False):
330+
if getattr(x, "_is_all_dates", False):
331331
# GH 5975, scipy.interp1d can't handle datetime64s
332332
x, new_x = x._values.astype("i8"), new_x.astype("i8")
333333

pandas/core/series.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -409,14 +409,20 @@ def _set_axis(self, axis: int, labels, fastpath: bool = False) -> None:
409409
if not fastpath:
410410
labels = ensure_index(labels)
411411

412-
is_all_dates = labels.is_all_dates
413-
if is_all_dates:
412+
if labels._is_all_dates:
414413
if not isinstance(labels, (DatetimeIndex, PeriodIndex, TimedeltaIndex)):
415414
try:
416415
labels = DatetimeIndex(labels)
417416
# need to set here because we changed the index
418417
if fastpath:
419418
self._mgr.set_axis(axis, labels)
419+
warnings.warn(
420+
"Automatically casting object-dtype Index of datetimes to "
421+
"DatetimeIndex is deprecated and will be removed in a "
422+
"future version. Explicitly cast to DatetimeIndex instead.",
423+
FutureWarning,
424+
stacklevel=3,
425+
)
420426
except (tslibs.OutOfBoundsDatetime, ValueError):
421427
# labels may exceeds datetime bounds,
422428
# or not be a DatetimeIndex

pandas/plotting/_matplotlib/core.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,7 @@ def get_label(i):
12381238
# would be too close together.
12391239
condition = (
12401240
not self._use_dynamic_x()
1241-
and (data.index.is_all_dates and self.use_index)
1241+
and (data.index._is_all_dates and self.use_index)
12421242
and (not self.subplots or (self.subplots and self.sharex))
12431243
)
12441244

pandas/tests/indexes/interval/test_interval.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ def test_is_all_dates(self):
871871
pd.Timestamp("2017-01-01 00:00:00"), pd.Timestamp("2018-01-01 00:00:00")
872872
)
873873
year_2017_index = pd.IntervalIndex([year_2017])
874-
assert not year_2017_index.is_all_dates
874+
assert not year_2017_index._is_all_dates
875875

876876
@pytest.mark.parametrize("key", [[5], (2, 3)])
877877
def test_get_value_non_scalar_errors(self, key):

pandas/tests/indexes/multi/test_equivalence.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def test_is_():
202202

203203

204204
def test_is_all_dates(idx):
205-
assert not idx.is_all_dates
205+
assert not idx._is_all_dates
206206

207207

208208
def test_is_numeric(idx):

pandas/tests/indexes/test_base.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,8 @@ def test_is_object(self, index, expected):
11531153
indirect=["index"],
11541154
)
11551155
def test_is_all_dates(self, index, expected):
1156-
assert index.is_all_dates is expected
1156+
with tm.assert_produces_warning(FutureWarning):
1157+
assert index.is_all_dates is expected
11571158

11581159
def test_summary(self, index):
11591160
self._check_method_works(Index._summary, index)

pandas/tests/indexing/test_indexing.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -554,15 +554,17 @@ def test_string_slice(self):
554554
# string indexing against datetimelike with object
555555
# dtype should properly raises KeyError
556556
df = DataFrame([1], Index([pd.Timestamp("2011-01-01")], dtype=object))
557-
assert df.index.is_all_dates
557+
assert df.index._is_all_dates
558558
with pytest.raises(KeyError, match="'2011'"):
559559
df["2011"]
560560

561561
with pytest.raises(KeyError, match="'2011'"):
562-
df.loc["2011", 0]
562+
with tm.assert_produces_warning(FutureWarning):
563+
# This does an is_all_dates check
564+
df.loc["2011", 0]
563565

564566
df = DataFrame()
565-
assert not df.index.is_all_dates
567+
assert not df.index._is_all_dates
566568
with pytest.raises(KeyError, match="'2011'"):
567569
df["2011"]
568570

pandas/tests/io/pytables/test_store.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -2384,10 +2384,16 @@ def test_series(self, setup_path):
23842384
ts = tm.makeTimeSeries()
23852385
self._check_roundtrip(ts, tm.assert_series_equal, path=setup_path)
23862386

2387-
ts2 = Series(ts.index, Index(ts.index, dtype=object))
2387+
with tm.assert_produces_warning(FutureWarning):
2388+
# auto-casting object->DatetimeIndex deprecated
2389+
ts2 = Series(ts.index, Index(ts.index, dtype=object))
23882390
self._check_roundtrip(ts2, tm.assert_series_equal, path=setup_path)
23892391

2390-
ts3 = Series(ts.values, Index(np.asarray(ts.index, dtype=object), dtype=object))
2392+
with tm.assert_produces_warning(FutureWarning):
2393+
# auto-casting object->DatetimeIndex deprecated
2394+
ts3 = Series(
2395+
ts.values, Index(np.asarray(ts.index, dtype=object), dtype=object)
2396+
)
23912397
self._check_roundtrip(
23922398
ts3, tm.assert_series_equal, path=setup_path, check_index_type=False
23932399
)

pandas/tests/series/test_alter_axes.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ def test_set_index_makes_timeseries(self):
5252

5353
s = Series(range(10))
5454
s.index = idx
55-
assert s.index.is_all_dates
55+
assert s.index._is_all_dates

pandas/tests/series/test_constructors.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ def test_scalar_conversion(self):
9494
def test_constructor(self, datetime_series):
9595
with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False):
9696
empty_series = Series()
97-
assert datetime_series.index.is_all_dates
97+
assert datetime_series.index._is_all_dates
9898

9999
# Pass in Series
100100
derived = Series(datetime_series)
101-
assert derived.index.is_all_dates
101+
assert derived.index._is_all_dates
102102

103103
assert tm.equalContents(derived.index, datetime_series.index)
104104
# Ensure new index is not created
@@ -109,9 +109,9 @@ def test_constructor(self, datetime_series):
109109
assert mixed.dtype == np.object_
110110
assert mixed[1] is np.NaN
111111

112-
assert not empty_series.index.is_all_dates
112+
assert not empty_series.index._is_all_dates
113113
with tm.assert_produces_warning(DeprecationWarning, check_stacklevel=False):
114-
assert not Series().index.is_all_dates
114+
assert not Series().index._is_all_dates
115115

116116
# exception raised is of type Exception
117117
with pytest.raises(Exception, match="Data must be 1-dimensional"):

pandas/tests/series/test_repr.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,9 @@ def test_timeseries_repr_object_dtype(self):
184184
index = Index(
185185
[datetime(2000, 1, 1) + timedelta(i) for i in range(1000)], dtype=object
186186
)
187-
ts = Series(np.random.randn(len(index)), index)
187+
with tm.assert_produces_warning(FutureWarning):
188+
# Index.is_all_dates deprecated
189+
ts = Series(np.random.randn(len(index)), index)
188190
repr(ts)
189191

190192
ts = tm.makeTimeSeries(1000)

pandas/tests/series/test_timeseries.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
class TestTimeSeries:
1010
def test_timeseries_coercion(self):
1111
idx = tm.makeDateIndex(10000)
12-
ser = Series(np.random.randn(len(idx)), idx.astype(object))
13-
assert ser.index.is_all_dates
12+
with tm.assert_produces_warning(FutureWarning):
13+
ser = Series(np.random.randn(len(idx)), idx.astype(object))
14+
with tm.assert_produces_warning(FutureWarning):
15+
assert ser.index.is_all_dates
1416
assert isinstance(ser.index, DatetimeIndex)
1517

1618
def test_contiguous_boolean_preserve_freq(self):

pandas/tests/window/moments/test_moments_rolling_apply.py

+20-14
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,16 @@ def test_center_reindex_series(raw, series):
122122
s = [f"x{x:d}" for x in range(12)]
123123
minp = 10
124124

125-
series_xp = (
126-
series.reindex(list(series.index) + s)
127-
.rolling(window=25, min_periods=minp)
128-
.apply(f, raw=raw)
129-
.shift(-12)
130-
.reindex(series.index)
131-
)
125+
warn = None if raw else FutureWarning
126+
with tm.assert_produces_warning(warn, check_stacklevel=False):
127+
# GH#36697 is_all_dates deprecated
128+
series_xp = (
129+
series.reindex(list(series.index) + s)
130+
.rolling(window=25, min_periods=minp)
131+
.apply(f, raw=raw)
132+
.shift(-12)
133+
.reindex(series.index)
134+
)
132135
series_rs = series.rolling(window=25, min_periods=minp, center=True).apply(
133136
f, raw=raw
134137
)
@@ -140,12 +143,15 @@ def test_center_reindex_frame(raw, frame):
140143
s = [f"x{x:d}" for x in range(12)]
141144
minp = 10
142145

143-
frame_xp = (
144-
frame.reindex(list(frame.index) + s)
145-
.rolling(window=25, min_periods=minp)
146-
.apply(f, raw=raw)
147-
.shift(-12)
148-
.reindex(frame.index)
149-
)
146+
warn = None if raw else FutureWarning
147+
with tm.assert_produces_warning(warn, check_stacklevel=False):
148+
# GH#36697 is_all_dates deprecated
149+
frame_xp = (
150+
frame.reindex(list(frame.index) + s)
151+
.rolling(window=25, min_periods=minp)
152+
.apply(f, raw=raw)
153+
.shift(-12)
154+
.reindex(frame.index)
155+
)
150156
frame_rs = frame.rolling(window=25, min_periods=minp, center=True).apply(f, raw=raw)
151157
tm.assert_frame_equal(frame_xp, frame_rs)

0 commit comments

Comments
 (0)