diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 3203dc083faf6..b78924b39073d 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -421,6 +421,7 @@ I/O Period ^^^^^^ - Bug in :class:`Period` addition silently wrapping around instead of raising ``OverflowError`` (:issue:`55503`) +- Bug in casting from :class:`PeriodDtype` with ``astype`` to ``datetime64`` or :class:`DatetimeTZDtype` with non-nanosecond unit incorrectly returning with nanosecond unit (:issue:`55958`) - Plotting @@ -433,6 +434,7 @@ Groupby/resample/rolling - Bug in :class:`.Rolling` where duplicate datetimelike indexes are treated as consecutive rather than equal with ``closed='left'`` and ``closed='neither'`` (:issue:`20712`) - Bug in :meth:`.DataFrameGroupBy.idxmin`, :meth:`.DataFrameGroupBy.idxmax`, :meth:`.SeriesGroupBy.idxmin`, and :meth:`.SeriesGroupBy.idxmax` would not retain :class:`.Categorical` dtype when the index was a :class:`.CategoricalIndex` that contained NA values (:issue:`54234`) - Bug in :meth:`.DataFrameGroupBy.transform` and :meth:`.SeriesGroupBy.transform` when ``observed=False`` and ``f="idxmin"`` or ``f="idxmax"`` would incorrectly raise on unobserved categories (:issue:`54234`) +- Bug in :meth:`DataFrame.asfreq` and :meth:`Series.asfreq` with a :class:`DatetimeIndex` with non-nanosecond resolution incorrectly converting to nanosecond resolution (:issue:`55958`) - Bug in :meth:`DataFrame.resample` not respecting ``closed`` and ``label`` arguments for :class:`~pandas.tseries.offsets.BusinessDay` (:issue:`55282`) - Bug in :meth:`DataFrame.resample` where bin edges were not correct for :class:`~pandas.tseries.offsets.BusinessDay` (:issue:`55281`) - Bug in :meth:`DataFrame.resample` where bin edges were not correct for :class:`~pandas.tseries.offsets.MonthBegin` (:issue:`55271`) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index f188b73b4fc64..25659d8738057 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -784,7 +784,8 @@ def astype(self, dtype, copy: bool = True): if lib.is_np_dtype(dtype, "M") or isinstance(dtype, DatetimeTZDtype): # GH#45038 match PeriodIndex behavior. tz = getattr(dtype, "tz", None) - return self.to_timestamp().tz_localize(tz) + unit = dtl.dtype_to_unit(dtype) + return self.to_timestamp().tz_localize(tz).as_unit(unit) return super().astype(dtype, copy=copy) diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 0827f9c8da4cc..14cd77ec8559b 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -2782,7 +2782,11 @@ def asfreq( new_obj.index = _asfreq_compat(obj.index, freq) else: - dti = date_range(obj.index.min(), obj.index.max(), freq=freq) + unit = None + if isinstance(obj.index, DatetimeIndex): + # TODO: should we disallow non-DatetimeIndex? + unit = obj.index.unit + dti = date_range(obj.index.min(), obj.index.max(), freq=freq, unit=unit) dti.name = obj.index.name new_obj = obj.reindex(dti, method=method, fill_value=fill_value) if normalize: diff --git a/pandas/tests/indexes/period/methods/test_astype.py b/pandas/tests/indexes/period/methods/test_astype.py index 07595b6b8c1dd..ba60ffd1fff4d 100644 --- a/pandas/tests/indexes/period/methods/test_astype.py +++ b/pandas/tests/indexes/period/methods/test_astype.py @@ -139,10 +139,13 @@ def test_astype_array_fallback(self): expected = np.array([True, True]) tm.assert_numpy_array_equal(result, expected) - def test_period_astype_to_timestamp(self): + def test_period_astype_to_timestamp(self, unit): + # GH#55958 pi = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M") - exp = DatetimeIndex(["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern") - res = pi.astype("datetime64[ns, US/Eastern]") + exp = DatetimeIndex( + ["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern" + ).as_unit(unit) + res = pi.astype(f"datetime64[{unit}, US/Eastern]") tm.assert_index_equal(res, exp) assert res.freq == exp.freq diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py index 21937a35629a0..0bda66de6a785 100644 --- a/pandas/tests/resample/test_datetime_index.py +++ b/pandas/tests/resample/test_datetime_index.py @@ -1263,10 +1263,14 @@ def test_resample_not_monotonic(unit): ), ], ) -def test_resample_median_bug_1688(dtype): +def test_resample_median_bug_1688(dtype, unit): + # GH#55958 + dti = DatetimeIndex( + [datetime(2012, 1, 1, 0, 0, 0), datetime(2012, 1, 1, 0, 5, 0)] + ).as_unit(unit) df = DataFrame( [1, 2], - index=[datetime(2012, 1, 1, 0, 0, 0), datetime(2012, 1, 1, 0, 5, 0)], + index=dti, dtype=dtype, )