From 1fb8811ece22d71727fdf597af19e069519cdae7 Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Thu, 15 Sep 2022 20:53:36 +0200 Subject: [PATCH] Backport PR #48555 on branch 1.5.x (DEPR: Series.astype(np.datetime64)) (#48569) Backport PR #48555: DEPR: Series.astype(np.datetime64) Co-authored-by: jbrockmendel --- doc/source/whatsnew/v1.5.0.rst | 1 + pandas/core/arrays/datetimes.py | 16 ++++++++++++++++ pandas/core/indexes/base.py | 6 ++++++ pandas/tests/series/methods/test_astype.py | 13 +++++++++++++ 4 files changed, 36 insertions(+) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index bed545fccba1c..bb9b052cd6e00 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -936,6 +936,7 @@ Other Deprecations - Deprecated the ``sort_columns`` argument in :meth:`DataFrame.plot` and :meth:`Series.plot` (:issue:`47563`). - Deprecated positional arguments for all but the first argument of :meth:`DataFrame.to_stata` and :func:`read_stata`, use keyword arguments instead (:issue:`48128`). - Deprecated the ``mangle_dupe_cols`` argument in :func:`read_csv`, :func:`read_fwf`, :func:`read_table` and :func:`read_excel`. The argument was never implemented, and a new argument where the renaming pattern can be specified will be added instead (:issue:`47718`) +- Deprecated allowing ``dtype='datetime64'`` or ``dtype=np.datetime64`` in :meth:`Series.astype`, use "datetime64[ns]" instead (:issue:`47844`) .. --------------------------------------------------------------------------- .. _whatsnew_150.performance: diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 64c15df64de3b..6b1f0bfac8f7a 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -630,6 +630,22 @@ def astype(self, dtype, copy: bool = True): return type(self)._simple_new(res_values, dtype=dtype) # TODO: preserve freq? + elif ( + self.tz is None + and is_datetime64_dtype(dtype) + and dtype != self.dtype + and is_unitless(dtype) + ): + # TODO(2.0): just fall through to dtl.DatetimeLikeArrayMixin.astype + warnings.warn( + "Passing unit-less datetime64 dtype to .astype is deprecated " + "and will raise in a future version. Pass 'datetime64[ns]' instead", + FutureWarning, + stacklevel=find_stack_level(inspect.currentframe()), + ) + # unit conversion e.g. datetime64[s] + return self._ndarray.astype(dtype) + elif is_period_dtype(dtype): return self.to_period(freq=dtype.freq) return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index ace3df3ae97a4..642a01821cb17 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -42,6 +42,7 @@ IncompatibleFrequency, OutOfBoundsDatetime, Timestamp, + is_unitless, tz_compare, ) from pandas._typing import ( @@ -1085,6 +1086,11 @@ def astype(self, dtype, copy: bool = True): values = self._data if isinstance(values, ExtensionArray): + if isinstance(dtype, np.dtype) and dtype.kind == "M" and is_unitless(dtype): + # TODO(2.0): remove this special-casing once this is enforced + # in DTA.astype + raise TypeError(f"Cannot cast {type(self).__name__} to dtype") + with rewrite_exception(type(values).__name__, type(self).__name__): new_values = values.astype(dtype, copy=copy) diff --git a/pandas/tests/series/methods/test_astype.py b/pandas/tests/series/methods/test_astype.py index 47d6cad0e1743..498225307b52e 100644 --- a/pandas/tests/series/methods/test_astype.py +++ b/pandas/tests/series/methods/test_astype.py @@ -30,6 +30,19 @@ class TestAstypeAPI: + def test_astype_unitless_dt64_deprecated(self): + # GH#47844 + ser = Series(["1970-01-01", "1970-01-01", "1970-01-01"], dtype="datetime64[ns]") + + msg = "Passing unit-less datetime64 dtype to .astype is deprecated and " + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.astype(np.datetime64) + tm.assert_series_equal(ser, res) + + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.astype("datetime64") + tm.assert_series_equal(ser, res) + def test_arg_for_errors_in_astype(self): # see GH#14878 ser = Series([1, 2, 3])