From d2d4e5cf3a73b42ee7fe50dd44cc0b84b8dfb7a6 Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Fri, 8 Aug 2025 22:05:49 +0300 Subject: [PATCH 1/3] Fix tz_localize(None) with Arrow timestamp --- pandas/core/arrays/arrow/array.py | 2 +- pandas/tests/extension/test_arrow.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index ad1d576bfec32..50b4c31c578a0 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -2953,7 +2953,7 @@ def _dt_tz_localize( if nonexistent_pa is None: raise NotImplementedError(f"{nonexistent=} is not supported") if tz is None: - result = self._pa_array.cast(pa.timestamp(self.dtype.pyarrow_dtype.unit)) + result = pc.local_timestamp(self._pa_array) else: result = pc.assume_timezone( self._pa_array, str(tz), ambiguous=ambiguous, nonexistent=nonexistent_pa diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index c3e1d33ec93df..8d0b49d6c7562 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -2686,7 +2686,6 @@ def test_dt_tz_localize_unsupported_tz_options(): ser.dt.tz_localize("UTC", nonexistent="NaT") -@pytest.mark.xfail(reason="Converts to UTC before localizing GH#61780") def test_dt_tz_localize_none(): ser = pd.Series( [datetime(year=2023, month=1, day=2, hour=3), None], From 89c3f6906f9664153f217d9eec541e25104441e0 Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Sat, 9 Aug 2025 09:56:17 +0300 Subject: [PATCH 2/3] Address failures on windows --- pandas/tests/extension/test_arrow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 8d0b49d6c7562..bef1e88fc0633 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -2686,7 +2686,9 @@ def test_dt_tz_localize_unsupported_tz_options(): ser.dt.tz_localize("UTC", nonexistent="NaT") -def test_dt_tz_localize_none(): +def test_dt_tz_localize_none(request): + _require_timezone_database(request) + ser = pd.Series( [datetime(year=2023, month=1, day=2, hour=3), None], dtype=ArrowDtype(pa.timestamp("ns", tz="US/Pacific")), From f8030fd1b63cff7c5eec3595b6a19f248ef94200 Mon Sep 17 00:00:00 2001 From: yuanx749 Date: Sat, 9 Aug 2025 12:01:35 +0300 Subject: [PATCH 3/3] Add note --- doc/source/whatsnew/v3.0.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 834477f2aa46a..54e328170de1e 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -732,6 +732,7 @@ Timedelta Timezones ^^^^^^^^^ - Bug in :meth:`DatetimeIndex.union`, :meth:`DatetimeIndex.intersection`, and :meth:`DatetimeIndex.symmetric_difference` changing timezone to UTC when merging two DatetimeIndex objects with the same timezone but different units (:issue:`60080`) +- Bug in :meth:`Series.dt.tz_localize` with a timezone-aware :class:`ArrowDtype` incorrectly converting to UTC when ``tz=None`` (:issue:`61780`) - Numeric