Skip to content
17 changes: 16 additions & 1 deletion pandas/core/tools/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@
is_list_like,
is_numeric_dtype,
)
from pandas.core.dtypes.dtypes import DatetimeTZDtype
from pandas.core.dtypes.dtypes import (
ArrowDtype,
DatetimeTZDtype,
)
from pandas.core.dtypes.generic import (
ABCDataFrame,
ABCSeries,
Expand Down Expand Up @@ -400,6 +403,18 @@ def _convert_listlike_datetimes(
arg = arg.tz_convert(None).tz_localize("utc")
return arg

elif isinstance(arg_dtype, ArrowDtype) and np.issubdtype(
arg_dtype.numpy_dtype, np.datetime64
):
# TODO: Combine with above if DTI/DTA supports Arrow timestamps
if utc:
import pyarrow as pa

# array attribute has to exist since arg is Index/Series at this point
arg_arr = arg.array._pa_array
arg._pa_array = arg_arr.cast(pa.timestamp(arg_arr.type.unit, "utc"))
return arg

elif lib.is_np_dtype(arg_dtype, "M"):
arg_dtype = cast(np.dtype, arg_dtype)
if not is_supported_unit(get_unit_from_dtype(arg_dtype)):
Expand Down
14 changes: 14 additions & 0 deletions pandas/tests/tools/test_to_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,20 @@ def test_to_datetime_dtarr(self, tz):
result = to_datetime(arr)
assert result is arr

@td.skip_if_no("pyarrow")
@pytest.mark.parametrize("utc", [True, False])
@pytest.mark.parametrize("tz", [None, "US/Central"])
def test_to_datetime_arrow(self, tz, utc):
import pyarrow as pa

dti = date_range("1965-04-03", periods=19, freq="2W", tz=tz)
dti_arrow = dti.astype(pd.ArrowDtype(pa.timestamp(unit="ns")))

result = to_datetime(dti_arrow, utc=utc)
expected = to_datetime(dti, utc=utc).astype("timestamp[ns][pyarrow]")
assert result is dti_arrow
tm.assert_index_equal(result, expected, exact=False)

def test_to_datetime_pydatetime(self):
actual = to_datetime(datetime(2008, 1, 15))
assert actual == datetime(2008, 1, 15)
Expand Down