From 7d2361a51302dd938be5fd2f2c9d7c91eb40da90 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 25 May 2021 07:45:03 -0700 Subject: [PATCH 1/2] DEPR: Series(dt64data, dtype=dt64tz) -> match DTA/DTI --- pandas/core/dtypes/cast.py | 14 ++++++++++++++ pandas/tests/series/test_constructors.py | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 40883dd8f747b..796959bd9aba0 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -1657,6 +1657,20 @@ def maybe_cast_to_datetime( # Numeric values are UTC at this point, # so localize and convert # equiv: Series(dta).astype(dtype) # though deprecated + if getattr(vdtype, "kind", None) == "M": + warnings.warn( + "In a future version, constructing a Series " + "from datetime64[ns] data and a " + "DatetimeTZDtype will interpret the data " + "as wall-times instead of " + "UTC times, matching the behavior of " + "DatetimeIndex. To treat the data as UTC " + "times, use pd.Series(data).dt" + ".tz_localize('UTC').tz_convert(dtype.tz) " + "or pd.Series(data.view('int64'), dtype=dtype)", + FutureWarning, + stacklevel=5, + ) value = dta.tz_localize("UTC").tz_convert(dtype.tz) except OutOfBoundsDatetime: diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index af730bf299336..6a7e18025b570 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -1094,7 +1094,9 @@ def test_construction_consistency(self): result = Series(ser.dt.tz_convert("UTC"), dtype=ser.dtype) tm.assert_series_equal(result, ser) - result = Series(ser.values, dtype=ser.dtype) + msg = "will interpret the data as wall-times" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = Series(ser.values, dtype=ser.dtype) tm.assert_series_equal(result, ser) @pytest.mark.parametrize( From 749c76ab1d7780b3e7d894504756b4dfc3fe8bdc Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 25 May 2021 07:54:01 -0700 Subject: [PATCH 2/2] whatsnew --- doc/source/whatsnew/v1.3.0.rst | 1 + pandas/core/dtypes/cast.py | 2 ++ pandas/tests/series/test_constructors.py | 12 ++++++++++++ 3 files changed, 15 insertions(+) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 7c209298c920a..9f131add781d0 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -682,6 +682,7 @@ Deprecations - Deprecated passing arguments as positional (except for ``"method"``) in :meth:`DataFrame.interpolate` and :meth:`Series.interpolate` (:issue:`41485`) - Deprecated passing arguments (apart from ``value``) as positional in :meth:`DataFrame.fillna` and :meth:`Series.fillna` (:issue:`41485`) - Deprecated construction of :class:`Series` or :class:`DataFrame` with ``DatetimeTZDtype`` data and ``datetime64[ns]`` dtype. Use ``Series(data).dt.tz_localize(None)`` instead (:issue:`41555`,:issue:`33401`) +- In a future version, constructing :class:`Series` or :class:`DataFrame` with ``datetime64[ns]`` data and ``DatetimeTZDtype`` will treat the data as wall-times instead of as UTC times (matching DatetimeIndex behavior). To treat the data as UTC times, use ``pd.Series(data).dt.tz_localize("UTC").dt.tz_convert(dtype.tz)`` or ``pd.Series(data.view("int64"), dtype=dtype)`` (:issue:`33401`) .. _whatsnew_130.deprecations.nuisance_columns: diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 796959bd9aba0..df79276f67386 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -1658,6 +1658,8 @@ def maybe_cast_to_datetime( # so localize and convert # equiv: Series(dta).astype(dtype) # though deprecated if getattr(vdtype, "kind", None) == "M": + # GH#24559, GH#33401 deprecate behavior inconsistent + # with DatetimeArray/DatetimeIndex warnings.warn( "In a future version, constructing a Series " "from datetime64[ns] data and a " diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index 6a7e18025b570..646d1f0ab1508 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -1096,9 +1096,21 @@ def test_construction_consistency(self): msg = "will interpret the data as wall-times" with tm.assert_produces_warning(FutureWarning, match=msg): + # deprecate behavior inconsistent with DatetimeIndex GH#33401 result = Series(ser.values, dtype=ser.dtype) tm.assert_series_equal(result, ser) + with tm.assert_produces_warning(None): + # one suggested alternative to the deprecated usage + middle = Series(ser.values).dt.tz_localize("UTC") + result = middle.dt.tz_convert(ser.dtype.tz) + tm.assert_series_equal(result, ser) + + with tm.assert_produces_warning(None): + # the other suggested alternative to the deprecated usage + result = Series(ser.values.view("int64"), dtype=ser.dtype) + tm.assert_series_equal(result, ser) + @pytest.mark.parametrize( "data_constructor", [list, np.array], ids=["list", "ndarray[object]"] )