From 509b2e9e51775f15de211c2f7fb952a08325a5a2 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 6 Sep 2025 08:26:55 -0700 Subject: [PATCH] BUG: Index.union with timestamp[s][pyarrow] --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/core/indexes/base.py | 6 +++++- pandas/tests/indexes/test_setops.py | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 7ec50137c3039..65d5527e9e71c 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -879,6 +879,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` and :meth:`DatetimeIndex.intersection` when ``unit`` was non-nanosecond (:issue:`59036`) +- Bug in :meth:`Index.union` with a ``pyarrow`` timestamp dtype incorrectly returning ``object`` dtype (:issue:`58421`) - Bug in :meth:`Series.dt.microsecond` producing incorrect results for pyarrow backed :class:`Series`. (:issue:`59154`) - Bug in :meth:`to_datetime` not respecting dayfirst if an uncommon date string was passed. (:issue:`58859`) - Bug in :meth:`to_datetime` on float array with missing values throwing ``FloatingPointError`` (:issue:`58419`) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 55dfb41b8c894..aacd95abbf6c1 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -5042,9 +5042,13 @@ def _get_join_target(self) -> np.ndarray: if isinstance(self._values, BaseMaskedArray): # This is only used if our array is monotonic, so no NAs present return self._values._data - elif isinstance(self._values, ArrowExtensionArray): + elif ( + isinstance(self._values, ArrowExtensionArray) + and self.dtype.kind not in "mM" + ): # This is only used if our array is monotonic, so no missing values # present + # "mM" cases will go through _get_engine_target and cast to i8 return self._values.to_numpy() # TODO: exclude ABCRangeIndex case here as it copies diff --git a/pandas/tests/indexes/test_setops.py b/pandas/tests/indexes/test_setops.py index 7cc74f4b3405c..6922803c325b3 100644 --- a/pandas/tests/indexes/test_setops.py +++ b/pandas/tests/indexes/test_setops.py @@ -10,6 +10,7 @@ import pytest from pandas._libs import lib +import pandas.util._test_decorators as td from pandas.core.dtypes.cast import find_common_type @@ -973,3 +974,13 @@ def test_union_string_array(self, any_string_dtype): result = idx1.union(idx2) expected = Index(["a", "b"], dtype=any_string_dtype) tm.assert_index_equal(result, expected) + + @td.skip_if_no("pyarrow") + def test_union_pyarrow_timestamp(self): + # GH#58421 + left = Index(["2020-01-01"], dtype="timestamp[s][pyarrow]") + right = Index(["2020-01-02"], dtype="timestamp[s][pyarrow]") + + res = left.union(right) + expected = Index(["2020-01-01", "2020-01-02"], dtype=left.dtype) + tm.assert_index_equal(res, expected)