diff --git a/pandas/core/ops/array_ops.py b/pandas/core/ops/array_ops.py index 9153eb25032e7..6f6972c34f0a9 100644 --- a/pandas/core/ops/array_ops.py +++ b/pandas/core/ops/array_ops.py @@ -195,6 +195,8 @@ def arithmetic_op(left: ArrayLike, right: Any, op): # NB: We assume that extract_array has already been called # on `left` and `right`. + # We need to special-case datetime64/timedelta64 dtypes (e.g. because numpy + # casts integer dtypes to timedelta64 when operating with timedelta64 - GH#22390) lvalues = ensure_wrapped_if_datetimelike(left) rvalues = ensure_wrapped_if_datetimelike(right) rvalues = _maybe_upcast_for_op(rvalues, lvalues.shape) @@ -439,11 +441,6 @@ def _maybe_upcast_for_op(obj, shape: Shape): Be careful to call this *after* determining the `name` attribute to be attached to the result of the arithmetic operation. """ - from pandas.core.arrays import ( - DatetimeArray, - TimedeltaArray, - ) - if type(obj) is timedelta: # GH#22390 cast up to Timedelta to rely on Timedelta # implementation; otherwise operation against numeric-dtype @@ -453,6 +450,8 @@ def _maybe_upcast_for_op(obj, shape: Shape): # GH#28080 numpy casts integer-dtype to datetime64 when doing # array[int] + datetime64, which we do not allow if isna(obj): + from pandas.core.arrays import DatetimeArray + # Avoid possible ambiguities with pd.NaT obj = obj.astype("datetime64[ns]") right = np.broadcast_to(obj, shape) @@ -462,6 +461,8 @@ def _maybe_upcast_for_op(obj, shape: Shape): elif isinstance(obj, np.timedelta64): if isna(obj): + from pandas.core.arrays import TimedeltaArray + # wrapping timedelta64("NaT") in Timedelta returns NaT, # which would incorrectly be treated as a datetime-NaT, so # we broadcast and wrap in a TimedeltaArray @@ -474,9 +475,4 @@ def _maybe_upcast_for_op(obj, shape: Shape): # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D') return Timedelta(obj) - elif isinstance(obj, np.ndarray) and obj.dtype.kind == "m": - # GH#22390 Unfortunately we need to special-case right-hand - # timedelta64 dtypes because numpy casts integer dtypes to - # timedelta64 when operating with timedelta64 - return TimedeltaArray._from_sequence(obj) return obj