diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index afb2f91f65ccd..7af5956cd768b 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -500,6 +500,7 @@ Datetimelike - Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` does not raise on Custom business days frequencies bigger then "1C" (:issue:`58664`) - Bug in :meth:`DatetimeIndex.is_year_start` and :meth:`DatetimeIndex.is_quarter_start` returning ``False`` on double-digit frequencies (:issue:`58523`) - Bug in :meth:`DatetimeIndex.union` when ``unit`` was non-nanosecond (:issue:`59036`) +- Bug in :meth:`Series.dt.microsecond` with:class:`ArrowDtype` returning incorrect values. (:issue:`59154`) - Bug in setting scalar values with mismatched resolution into arrays with non-nanosecond ``datetime64``, ``timedelta64`` or :class:`DatetimeTZDtype` incorrectly truncating those scalars (:issue:`56410`) Timedelta diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index 4ff7553af2b69..1ba6ad3f8cabd 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -2794,7 +2794,14 @@ def _dt_days_in_month(self) -> Self: @property def _dt_microsecond(self) -> Self: - return type(self)(pc.microsecond(self._pa_array)) + us = pc.microsecond(self._pa_array) + ms_us = pc.multiply( + pc.millisecond(self._pa_array), pa.scalar(1000, type=us.type) + ) + s_us = pc.multiply( + pc.second(self._pa_array), pa.scalar(1_000_000, type=us.type) + ) + return type(self)(pc.add(pc.add(ms_us, s_us), us)) @property def _dt_minute(self) -> Self: diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index f2e9d2321f33e..c7840cdbf3da9 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -3536,3 +3536,13 @@ def test_map_numeric_na_action(): result = ser.map(lambda x: 42, na_action="ignore") expected = pd.Series([42.0, 42.0, np.nan], dtype="float64") tm.assert_series_equal(result, expected) + + +def test_microsecond(): + series = pd.Series( + [946684800000000000, 946684800015000000, 946684800030000000], + dtype=ArrowDtype(pa.timestamp("ns")), + ) + result = series.dt.microsecond + expected = pd.Series([0, 15000, 30000], dtype="int64[pyarrow]") + tm.assert_series_equal(result, expected)