@@ -1160,33 +1160,36 @@ def _add_datetimelike_scalar(self, other) -> DatetimeArray:
1160
1160
from pandas .core .arrays .datetimes import tz_to_dtype
1161
1161
1162
1162
assert other is not NaT
1163
- other = Timestamp (other )
1164
- if other is NaT :
1163
+ if isna (other ):
1164
+ # i.e. np.datetime64(" NaT")
1165
1165
# In this case we specifically interpret NaT as a datetime, not
1166
1166
# the timedelta interpretation we would get by returning self + NaT
1167
1167
result = self ._ndarray + NaT .to_datetime64 ().astype (f"M8[{ self ._unit } ]" )
1168
1168
# Preserve our resolution
1169
1169
return DatetimeArray ._simple_new (result , dtype = result .dtype )
1170
1170
1171
+ other = Timestamp (other )
1171
1172
self , other = self ._ensure_matching_resos (other )
1172
1173
self = cast ("TimedeltaArray" , self )
1173
1174
1174
- i8 = self .asi8
1175
- result = checked_add_with_arr (i8 , other .value , arr_mask = self ._isnan )
1175
+ other_i8 , o_mask = self ._get_i8_values_and_mask (other )
1176
+ result = checked_add_with_arr (
1177
+ self .asi8 , other_i8 , arr_mask = self ._isnan , b_mask = o_mask
1178
+ )
1179
+ res_values = result .view (f"M8[{ self ._unit } ]" )
1176
1180
1177
1181
dtype = tz_to_dtype (tz = other .tz , unit = self ._unit )
1178
1182
res_values = result .view (f"M8[{ self ._unit } ]" )
1179
- return DatetimeArray ._simple_new (res_values , dtype = dtype , freq = self .freq )
1183
+ new_freq = self ._get_arithmetic_result_freq (other )
1184
+ return DatetimeArray ._simple_new (res_values , dtype = dtype , freq = new_freq )
1180
1185
1181
1186
@final
1182
- def _add_datetime_arraylike (self , other ) -> DatetimeArray :
1187
+ def _add_datetime_arraylike (self , other : DatetimeArray ) -> DatetimeArray :
1183
1188
if not is_timedelta64_dtype (self .dtype ):
1184
1189
raise TypeError (
1185
1190
f"cannot add { type (self ).__name__ } and { type (other ).__name__ } "
1186
1191
)
1187
1192
1188
- # At this point we have already checked that other.dtype is datetime64
1189
- other = ensure_wrapped_if_datetimelike (other )
1190
1193
# defer to DatetimeArray.__add__
1191
1194
return other + self
1192
1195
@@ -1208,15 +1211,14 @@ def _sub_datetimelike_scalar(self, other: datetime | np.datetime64):
1208
1211
return self ._sub_datetimelike (ts )
1209
1212
1210
1213
@final
1211
- def _sub_datetime_arraylike (self , other ):
1214
+ def _sub_datetime_arraylike (self , other : DatetimeArray ):
1212
1215
if self .dtype .kind != "M" :
1213
1216
raise TypeError (f"cannot subtract a datelike from a { type (self ).__name__ } " )
1214
1217
1215
1218
if len (self ) != len (other ):
1216
1219
raise ValueError ("cannot add indices of unequal length" )
1217
1220
1218
1221
self = cast ("DatetimeArray" , self )
1219
- other = ensure_wrapped_if_datetimelike (other )
1220
1222
1221
1223
self , other = self ._ensure_matching_resos (other )
1222
1224
return self ._sub_datetimelike (other )
@@ -1242,16 +1244,6 @@ def _sub_datetimelike(self, other: Timestamp | DatetimeArray) -> TimedeltaArray:
1242
1244
new_freq = self ._get_arithmetic_result_freq (other )
1243
1245
return TimedeltaArray ._simple_new (res_m8 , dtype = res_m8 .dtype , freq = new_freq )
1244
1246
1245
- @final
1246
- def _sub_period (self , other : Period ) -> npt .NDArray [np .object_ ]:
1247
- if not is_period_dtype (self .dtype ):
1248
- raise TypeError (f"cannot subtract Period from a { type (self ).__name__ } " )
1249
-
1250
- # If the operation is well-defined, we return an object-dtype ndarray
1251
- # of DateOffsets. Null entries are filled with pd.NaT
1252
- self ._check_compatible_with (other )
1253
- return self ._sub_periodlike (other )
1254
-
1255
1247
@final
1256
1248
def _add_period (self , other : Period ) -> PeriodArray :
1257
1249
if not is_timedelta64_dtype (self .dtype ):
@@ -1286,9 +1278,7 @@ def _add_timedeltalike_scalar(self, other):
1286
1278
other = Timedelta (other )._as_unit (self ._unit )
1287
1279
return self ._add_timedeltalike (other )
1288
1280
1289
- def _add_timedelta_arraylike (
1290
- self , other : TimedeltaArray | npt .NDArray [np .timedelta64 ]
1291
- ):
1281
+ def _add_timedelta_arraylike (self , other : TimedeltaArray ):
1292
1282
"""
1293
1283
Add a delta of a TimedeltaIndex
1294
1284
@@ -1301,12 +1291,10 @@ def _add_timedelta_arraylike(
1301
1291
if len (self ) != len (other ):
1302
1292
raise ValueError ("cannot add indices of unequal length" )
1303
1293
1304
- other = ensure_wrapped_if_datetimelike (other )
1305
- tda = cast ("TimedeltaArray" , other )
1306
1294
self = cast ("DatetimeArray | TimedeltaArray" , self )
1307
1295
1308
- self , tda = self ._ensure_matching_resos (tda )
1309
- return self ._add_timedeltalike (tda )
1296
+ self , other = self ._ensure_matching_resos (other )
1297
+ return self ._add_timedeltalike (other )
1310
1298
1311
1299
@final
1312
1300
def _add_timedeltalike (self , other : Timedelta | TimedeltaArray ):
@@ -1356,21 +1344,17 @@ def _sub_nat(self):
1356
1344
return result .view ("timedelta64[ns]" )
1357
1345
1358
1346
@final
1359
- def _sub_period_array (self , other : PeriodArray ) -> npt .NDArray [np .object_ ]:
1347
+ def _sub_periodlike (self , other : Period | PeriodArray ) -> npt .NDArray [np .object_ ]:
1348
+ # If the operation is well-defined, we return an object-dtype ndarray
1349
+ # of DateOffsets. Null entries are filled with pd.NaT
1360
1350
if not is_period_dtype (self .dtype ):
1361
1351
raise TypeError (
1362
- f"cannot subtract { other . dtype } -dtype from { type (self ).__name__ } "
1352
+ f"cannot subtract { type ( other ). __name__ } from { type (self ).__name__ } "
1363
1353
)
1364
1354
1365
1355
self = cast ("PeriodArray" , self )
1366
- self ._require_matching_freq (other )
1367
-
1368
- return self ._sub_periodlike (other )
1356
+ self ._check_compatible_with (other )
1369
1357
1370
- @final
1371
- def _sub_periodlike (self , other : Period | PeriodArray ) -> npt .NDArray [np .object_ ]:
1372
- # caller is responsible for calling
1373
- # require_matching_freq/check_compatible_with
1374
1358
other_i8 , o_mask = self ._get_i8_values_and_mask (other )
1375
1359
new_i8_data = checked_add_with_arr (
1376
1360
self .asi8 , - other_i8 , arr_mask = self ._isnan , b_mask = o_mask
@@ -1465,6 +1449,7 @@ def _time_shift(
1465
1449
@unpack_zerodim_and_defer ("__add__" )
1466
1450
def __add__ (self , other ):
1467
1451
other_dtype = getattr (other , "dtype" , None )
1452
+ other = ensure_wrapped_if_datetimelike (other )
1468
1453
1469
1454
# scalar others
1470
1455
if other is NaT :
@@ -1525,6 +1510,7 @@ def __radd__(self, other):
1525
1510
def __sub__ (self , other ):
1526
1511
1527
1512
other_dtype = getattr (other , "dtype" , None )
1513
+ other = ensure_wrapped_if_datetimelike (other )
1528
1514
1529
1515
# scalar others
1530
1516
if other is NaT :
@@ -1546,7 +1532,7 @@ def __sub__(self, other):
1546
1532
)
1547
1533
1548
1534
elif isinstance (other , Period ):
1549
- result = self ._sub_period (other )
1535
+ result = self ._sub_periodlike (other )
1550
1536
1551
1537
# array-like others
1552
1538
elif is_timedelta64_dtype (other_dtype ):
@@ -1560,7 +1546,7 @@ def __sub__(self, other):
1560
1546
result = self ._sub_datetime_arraylike (other )
1561
1547
elif is_period_dtype (other_dtype ):
1562
1548
# PeriodIndex
1563
- result = self ._sub_period_array (other )
1549
+ result = self ._sub_periodlike (other )
1564
1550
elif is_integer_dtype (other_dtype ):
1565
1551
if not is_period_dtype (self .dtype ):
1566
1552
raise integer_op_not_supported (self )
0 commit comments