2525 get_upcast_box ,
2626)
2727
28+
29+ def assert_dtype (obj , expected_dtype ):
30+ """
31+ Helper to check the dtype for a Series, Index, or single-column DataFrame.
32+ """
33+ if isinstance (obj , DataFrame ):
34+ dtype = obj .dtypes .iat [0 ]
35+ else :
36+ dtype = obj .dtype
37+
38+ assert dtype == expected_dtype
39+
40+
2841# ------------------------------------------------------------------
2942# Timedelta64[ns] dtype Comparisons
3043
@@ -522,19 +535,35 @@ def test_tda_add_sub_index(self):
522535 # -------------------------------------------------------------
523536 # Binary operations TimedeltaIndex and timedelta-like
524537
525- def test_tdi_iadd_timedeltalike (self , two_hours ):
538+ def test_tdi_iadd_timedeltalike (self , two_hours , box_with_array ):
526539 # only test adding/sub offsets as + is now numeric
527540 rng = timedelta_range ("1 days" , "10 days" )
528541 expected = timedelta_range ("1 days 02:00:00" , "10 days 02:00:00" , freq = "D" )
542+
543+ rng = tm .box_expected (rng , box_with_array )
544+ expected = tm .box_expected (expected , box_with_array )
545+
546+ orig_rng = rng
529547 rng += two_hours
530- tm .assert_index_equal (rng , expected )
548+ tm .assert_equal (rng , expected )
549+ if box_with_array is not pd .Index :
550+ # Check that operation is actually inplace
551+ tm .assert_equal (orig_rng , expected )
531552
532- def test_tdi_isub_timedeltalike (self , two_hours ):
553+ def test_tdi_isub_timedeltalike (self , two_hours , box_with_array ):
533554 # only test adding/sub offsets as - is now numeric
534555 rng = timedelta_range ("1 days" , "10 days" )
535556 expected = timedelta_range ("0 days 22:00:00" , "9 days 22:00:00" )
557+
558+ rng = tm .box_expected (rng , box_with_array )
559+ expected = tm .box_expected (expected , box_with_array )
560+
561+ orig_rng = rng
536562 rng -= two_hours
537- tm .assert_index_equal (rng , expected )
563+ tm .assert_equal (rng , expected )
564+ if box_with_array is not pd .Index :
565+ # Check that operation is actually inplace
566+ tm .assert_equal (orig_rng , expected )
538567
539568 # -------------------------------------------------------------
540569
@@ -1013,15 +1042,6 @@ def test_td64arr_add_datetime64_nat(self, box_with_array):
10131042 # ------------------------------------------------------------------
10141043 # Invalid __add__/__sub__ operations
10151044
1016- # TODO: moved from frame tests; needs parametrization/de-duplication
1017- def test_td64_df_add_int_frame (self ):
1018- # GH#22696 Check that we don't dispatch to numpy implementation,
1019- # which treats int64 as m8[ns]
1020- tdi = pd .timedelta_range ("1" , periods = 3 )
1021- df = tdi .to_frame ()
1022- other = pd .DataFrame ([1 , 2 , 3 ], index = tdi ) # indexed like `df`
1023- assert_invalid_addsub_type (df , other )
1024-
10251045 @pytest .mark .parametrize ("pi_freq" , ["D" , "W" , "Q" , "H" ])
10261046 @pytest .mark .parametrize ("tdi_freq" , [None , "H" ])
10271047 def test_td64arr_sub_periodlike (self , box_with_array , tdi_freq , pi_freq ):
@@ -1100,6 +1120,9 @@ def test_td64arr_add_sub_int(self, box_with_array, one):
11001120
11011121 def test_td64arr_add_sub_integer_array (self , box_with_array ):
11021122 # GH#19959, deprecated GH#22535
1123+ # GH#22696 for DataFrame case, check that we don't dispatch to numpy
1124+ # implementation, which treats int64 as m8[ns]
1125+
11031126 rng = timedelta_range ("1 days 09:00:00" , freq = "H" , periods = 3 )
11041127 tdarr = tm .box_expected (rng , box_with_array )
11051128 other = tm .box_expected ([4 , 3 , 2 ], box_with_array )
@@ -1119,60 +1142,6 @@ def test_td64arr_addsub_integer_array_no_freq(self, box_with_array):
11191142 # ------------------------------------------------------------------
11201143 # Operations with timedelta-like others
11211144
1122- # TODO: this was taken from tests.series.test_ops; de-duplicate
1123- def test_operators_timedelta64_with_timedelta (self , scalar_td ):
1124- # smoke tests
1125- td1 = Series ([timedelta (minutes = 5 , seconds = 3 )] * 3 )
1126- td1 .iloc [2 ] = np .nan
1127-
1128- td1 + scalar_td
1129- scalar_td + td1
1130- td1 - scalar_td
1131- scalar_td - td1
1132- td1 / scalar_td
1133- scalar_td / td1
1134-
1135- # TODO: this was taken from tests.series.test_ops; de-duplicate
1136- def test_timedelta64_operations_with_timedeltas (self ):
1137- # td operate with td
1138- td1 = Series ([timedelta (minutes = 5 , seconds = 3 )] * 3 )
1139- td2 = timedelta (minutes = 5 , seconds = 4 )
1140- result = td1 - td2
1141- expected = Series ([timedelta (seconds = 0 )] * 3 ) - Series (
1142- [timedelta (seconds = 1 )] * 3
1143- )
1144- assert result .dtype == "m8[ns]"
1145- tm .assert_series_equal (result , expected )
1146-
1147- result2 = td2 - td1
1148- expected = Series ([timedelta (seconds = 1 )] * 3 ) - Series (
1149- [timedelta (seconds = 0 )] * 3
1150- )
1151- tm .assert_series_equal (result2 , expected )
1152-
1153- # roundtrip
1154- tm .assert_series_equal (result + td2 , td1 )
1155-
1156- # Now again, using pd.to_timedelta, which should build
1157- # a Series or a scalar, depending on input.
1158- td1 = Series (pd .to_timedelta (["00:05:03" ] * 3 ))
1159- td2 = pd .to_timedelta ("00:05:04" )
1160- result = td1 - td2
1161- expected = Series ([timedelta (seconds = 0 )] * 3 ) - Series (
1162- [timedelta (seconds = 1 )] * 3
1163- )
1164- assert result .dtype == "m8[ns]"
1165- tm .assert_series_equal (result , expected )
1166-
1167- result2 = td2 - td1
1168- expected = Series ([timedelta (seconds = 1 )] * 3 ) - Series (
1169- [timedelta (seconds = 0 )] * 3
1170- )
1171- tm .assert_series_equal (result2 , expected )
1172-
1173- # roundtrip
1174- tm .assert_series_equal (result + td2 , td1 )
1175-
11761145 def test_td64arr_add_td64_array (self , box_with_array ):
11771146 box = box_with_array
11781147 dti = pd .date_range ("2016-01-01" , periods = 3 )
@@ -1203,7 +1172,6 @@ def test_td64arr_sub_td64_array(self, box_with_array):
12031172 result = tdarr - tdi
12041173 tm .assert_equal (result , expected )
12051174
1206- # TODO: parametrize over [add, sub, radd, rsub]?
12071175 @pytest .mark .parametrize (
12081176 "names" ,
12091177 [
@@ -1232,17 +1200,11 @@ def test_td64arr_add_sub_tdi(self, box, names):
12321200
12331201 result = tdi + ser
12341202 tm .assert_equal (result , expected )
1235- if box is not pd .DataFrame :
1236- assert result .dtype == "timedelta64[ns]"
1237- else :
1238- assert result .dtypes [0 ] == "timedelta64[ns]"
1203+ assert_dtype (result , "timedelta64[ns]" )
12391204
12401205 result = ser + tdi
12411206 tm .assert_equal (result , expected )
1242- if box is not pd .DataFrame :
1243- assert result .dtype == "timedelta64[ns]"
1244- else :
1245- assert result .dtypes [0 ] == "timedelta64[ns]"
1207+ assert_dtype (result , "timedelta64[ns]" )
12461208
12471209 expected = Series (
12481210 [Timedelta (hours = - 3 ), Timedelta (days = 1 , hours = - 4 )], name = names [2 ]
@@ -1251,17 +1213,11 @@ def test_td64arr_add_sub_tdi(self, box, names):
12511213
12521214 result = tdi - ser
12531215 tm .assert_equal (result , expected )
1254- if box is not pd .DataFrame :
1255- assert result .dtype == "timedelta64[ns]"
1256- else :
1257- assert result .dtypes [0 ] == "timedelta64[ns]"
1216+ assert_dtype (result , "timedelta64[ns]" )
12581217
12591218 result = ser - tdi
12601219 tm .assert_equal (result , - expected )
1261- if box is not pd .DataFrame :
1262- assert result .dtype == "timedelta64[ns]"
1263- else :
1264- assert result .dtypes [0 ] == "timedelta64[ns]"
1220+ assert_dtype (result , "timedelta64[ns]" )
12651221
12661222 def test_td64arr_add_sub_td64_nat (self , box_with_array ):
12671223 # GH#23320 special handling for timedelta64("NaT")
@@ -1296,6 +1252,7 @@ def test_td64arr_sub_NaT(self, box_with_array):
12961252
12971253 def test_td64arr_add_timedeltalike (self , two_hours , box_with_array ):
12981254 # only test adding/sub offsets as + is now numeric
1255+ # GH#10699 for Tick cases
12991256 box = box_with_array
13001257 rng = timedelta_range ("1 days" , "10 days" )
13011258 expected = timedelta_range ("1 days 02:00:00" , "10 days 02:00:00" , freq = "D" )
@@ -1305,8 +1262,12 @@ def test_td64arr_add_timedeltalike(self, two_hours, box_with_array):
13051262 result = rng + two_hours
13061263 tm .assert_equal (result , expected )
13071264
1265+ result = two_hours + rng
1266+ tm .assert_equal (result , expected )
1267+
13081268 def test_td64arr_sub_timedeltalike (self , two_hours , box_with_array ):
13091269 # only test adding/sub offsets as - is now numeric
1270+ # GH#10699 for Tick cases
13101271 box = box_with_array
13111272 rng = timedelta_range ("1 days" , "10 days" )
13121273 expected = timedelta_range ("0 days 22:00:00" , "9 days 22:00:00" )
@@ -1317,46 +1278,12 @@ def test_td64arr_sub_timedeltalike(self, two_hours, box_with_array):
13171278 result = rng - two_hours
13181279 tm .assert_equal (result , expected )
13191280
1281+ result = two_hours - rng
1282+ tm .assert_equal (result , - expected )
1283+
13201284 # ------------------------------------------------------------------
13211285 # __add__/__sub__ with DateOffsets and arrays of DateOffsets
13221286
1323- # TODO: this was taken from tests.series.test_operators; de-duplicate
1324- def test_timedelta64_operations_with_DateOffset (self ):
1325- # GH#10699
1326- td = Series ([timedelta (minutes = 5 , seconds = 3 )] * 3 )
1327- result = td + pd .offsets .Minute (1 )
1328- expected = Series ([timedelta (minutes = 6 , seconds = 3 )] * 3 )
1329- tm .assert_series_equal (result , expected )
1330-
1331- result = td - pd .offsets .Minute (1 )
1332- expected = Series ([timedelta (minutes = 4 , seconds = 3 )] * 3 )
1333- tm .assert_series_equal (result , expected )
1334-
1335- with tm .assert_produces_warning (PerformanceWarning ):
1336- result = td + Series (
1337- [pd .offsets .Minute (1 ), pd .offsets .Second (3 ), pd .offsets .Hour (2 )]
1338- )
1339- expected = Series (
1340- [
1341- timedelta (minutes = 6 , seconds = 3 ),
1342- timedelta (minutes = 5 , seconds = 6 ),
1343- timedelta (hours = 2 , minutes = 5 , seconds = 3 ),
1344- ]
1345- )
1346- tm .assert_series_equal (result , expected )
1347-
1348- result = td + pd .offsets .Minute (1 ) + pd .offsets .Second (12 )
1349- expected = Series ([timedelta (minutes = 6 , seconds = 15 )] * 3 )
1350- tm .assert_series_equal (result , expected )
1351-
1352- # valid DateOffsets
1353- for do in ["Hour" , "Minute" , "Second" , "Day" , "Micro" , "Milli" , "Nano" ]:
1354- op = getattr (pd .offsets , do )
1355- td + op (5 )
1356- op (5 ) + td
1357- td - op (5 )
1358- op (5 ) - td
1359-
13601287 @pytest .mark .parametrize (
13611288 "names" , [(None , None , None ), ("foo" , "bar" , None ), ("foo" , "foo" , "foo" )]
13621289 )
@@ -1561,26 +1488,6 @@ class TestTimedeltaArraylikeMulDivOps:
15611488 # Tests for timedelta64[ns]
15621489 # __mul__, __rmul__, __div__, __rdiv__, __floordiv__, __rfloordiv__
15631490
1564- # TODO: Moved from tests.series.test_operators; needs cleanup
1565- @pytest .mark .parametrize ("m" , [1 , 3 , 10 ])
1566- @pytest .mark .parametrize ("unit" , ["D" , "h" , "m" , "s" , "ms" , "us" , "ns" ])
1567- def test_timedelta64_conversions (self , m , unit ):
1568- startdate = Series (pd .date_range ("2013-01-01" , "2013-01-03" ))
1569- enddate = Series (pd .date_range ("2013-03-01" , "2013-03-03" ))
1570-
1571- ser = enddate - startdate
1572- ser [2 ] = np .nan
1573-
1574- # op
1575- expected = Series ([x / np .timedelta64 (m , unit ) for x in ser ])
1576- result = ser / np .timedelta64 (m , unit )
1577- tm .assert_series_equal (result , expected )
1578-
1579- # reverse op
1580- expected = Series ([Timedelta (np .timedelta64 (m , unit )) / x for x in ser ])
1581- result = np .timedelta64 (m , unit ) / ser
1582- tm .assert_series_equal (result , expected )
1583-
15841491 # ------------------------------------------------------------------
15851492 # Multiplication
15861493 # organized with scalar others first, then array-like
@@ -1734,6 +1641,29 @@ def test_td64arr_div_tdlike_scalar(self, two_hours, box_with_array):
17341641 expected = 1 / expected
17351642 tm .assert_equal (result , expected )
17361643
1644+ @pytest .mark .parametrize ("m" , [1 , 3 , 10 ])
1645+ @pytest .mark .parametrize ("unit" , ["D" , "h" , "m" , "s" , "ms" , "us" , "ns" ])
1646+ def test_td64arr_div_td64_scalar (self , m , unit , box_with_array ):
1647+ startdate = Series (pd .date_range ("2013-01-01" , "2013-01-03" ))
1648+ enddate = Series (pd .date_range ("2013-03-01" , "2013-03-03" ))
1649+
1650+ ser = enddate - startdate
1651+ ser [2 ] = np .nan
1652+ flat = ser
1653+ ser = tm .box_expected (ser , box_with_array )
1654+
1655+ # op
1656+ expected = Series ([x / np .timedelta64 (m , unit ) for x in flat ])
1657+ expected = tm .box_expected (expected , box_with_array )
1658+ result = ser / np .timedelta64 (m , unit )
1659+ tm .assert_equal (result , expected )
1660+
1661+ # reverse op
1662+ expected = Series ([Timedelta (np .timedelta64 (m , unit )) / x for x in flat ])
1663+ expected = tm .box_expected (expected , box_with_array )
1664+ result = np .timedelta64 (m , unit ) / ser
1665+ tm .assert_equal (result , expected )
1666+
17371667 def test_td64arr_div_tdlike_scalar_with_nat (self , two_hours , box_with_array ):
17381668 rng = TimedeltaIndex (["1 days" , pd .NaT , "2 days" ], name = "foo" )
17391669 expected = pd .Float64Index ([12 , np .nan , 24 ], name = "foo" )
0 commit comments