Skip to content

Commit 3c7ae75

Browse files
committed
API: stop silent conversion of object-Index to DatetimeIndex
1 parent 2e7f5a3 commit 3c7ae75

File tree

4 files changed

+10
-34
lines changed

4 files changed

+10
-34
lines changed

doc/source/whatsnew/v2.0.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ Other API changes
127127
- Passing ``dtype`` of "timedelta64[s]", "timedelta64[ms]", or "timedelta64[us]" to :class:`TimedeltaIndex`, :class:`Series`, or :class:`DataFrame` constructors will now retain that dtype instead of casting to "timedelta64[ns]"; passing a dtype with lower resolution for :class:`Series` or :class:`DataFrame` will be cast to the lowest supported resolution "timedelta64[s]" (:issue:`49014`)
128128
- Passing a ``np.datetime64`` object with non-nanosecond resolution to :class:`Timestamp` will retain the input resolution if it is "s", "ms", or "ns"; otherwise it will be cast to the closest supported resolution (:issue:`49008`)
129129
- The ``other`` argument in :meth:`DataFrame.mask` and :meth:`Series.mask` now defaults to ``no_default`` instead of ``np.nan`` consistent with :meth:`DataFrame.where` and :meth:`Series.where`. Entries will be filled with the corresponding NULL value (``np.nan`` for numpy dtypes, ``pd.NA`` for extension dtypes). (:issue:`49111`)
130+
- When creating a :class:`Series` with a object-dtype :class:`Index` of datetime objects, pandas no longer silently converts the index to a :class:`DatetimeIndex` (:issue:`?`)
131+
-
130132

131133
.. ---------------------------------------------------------------------------
132134
.. _whatsnew_200.deprecations:

pandas/core/generic.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,12 @@ def _set_axis_nocheck(self, labels, axis: Axis, inplace: bool_t, copy: bool_t):
825825
setattr(obj, obj._get_axis_name(axis), labels)
826826
return obj
827827

828+
@final
828829
def _set_axis(self, axis: AxisInt, labels: AnyArrayLike | list) -> None:
830+
"""
831+
This is called from the cython code when we set the `index` attribute
832+
directly, e.g. `series.index = [1, 2, 3]`.
833+
"""
829834
labels = ensure_index(labels)
830835
self._mgr.set_axis(axis, labels)
831836
self._clear_item_cache()

pandas/core/series.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
lib,
3030
properties,
3131
reshape,
32-
tslibs,
3332
)
3433
from pandas._libs.lib import no_default
3534
from pandas._typing import (
@@ -132,13 +131,11 @@
132131
)
133132
from pandas.core.indexes.accessors import CombinedDatetimelikeProperties
134133
from pandas.core.indexes.api import (
135-
CategoricalIndex,
136134
DatetimeIndex,
137135
Float64Index,
138136
Index,
139137
MultiIndex,
140138
PeriodIndex,
141-
TimedeltaIndex,
142139
default_index,
143140
ensure_index,
144141
)
@@ -570,36 +567,6 @@ def _constructor_expanddim(self) -> Callable[..., DataFrame]:
570567
def _can_hold_na(self) -> bool:
571568
return self._mgr._can_hold_na
572569

573-
def _set_axis(self, axis: AxisInt, labels: AnyArrayLike | list) -> None:
574-
"""
575-
Override generic, we want to set the _typ here.
576-
577-
This is called from the cython code when we set the `index` attribute
578-
directly, e.g. `series.index = [1, 2, 3]`.
579-
"""
580-
labels = ensure_index(labels)
581-
582-
if labels._is_all_dates and not (
583-
type(labels) is Index and not isinstance(labels.dtype, np.dtype)
584-
):
585-
# exclude e.g. timestamp[ns][pyarrow] dtype from this casting
586-
deep_labels = labels
587-
if isinstance(labels, CategoricalIndex):
588-
deep_labels = labels.categories
589-
590-
if not isinstance(
591-
deep_labels, (DatetimeIndex, PeriodIndex, TimedeltaIndex)
592-
):
593-
try:
594-
labels = DatetimeIndex(labels)
595-
except (tslibs.OutOfBoundsDatetime, ValueError):
596-
# labels may exceeds datetime bounds,
597-
# or not be a DatetimeIndex
598-
pass
599-
600-
# The ensure_index call above ensures we have an Index object
601-
self._mgr.set_axis(axis, labels)
602-
603570
# ndarray compatibility
604571
@property
605572
def dtype(self) -> DtypeObj:

pandas/tests/series/test_constructors.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,9 @@ def test_series_constructor_datetimelike_index_coercion(self):
19841984
ser = Series(np.random.randn(len(idx)), idx.astype(object))
19851985
with tm.assert_produces_warning(FutureWarning):
19861986
assert ser.index.is_all_dates
1987-
assert isinstance(ser.index, DatetimeIndex)
1987+
# as of 2.0, we no longer silently cast the object-dtype index
1988+
# to DatetimeIndex
1989+
assert not isinstance(ser.index, DatetimeIndex)
19881990

19891991
def test_series_constructor_infer_multiindex(self):
19901992
index_lists = [["a", "a", "b", "b"], ["x", "y", "x", "y"]]

0 commit comments

Comments
 (0)