Skip to content

Commit 74dc8ba

Browse files
fix raise of TypeError when subtracting timedelta array
closes #21980
1 parent 716efd3 commit 74dc8ba

File tree

3 files changed

+115
-5
lines changed

3 files changed

+115
-5
lines changed

doc/source/whatsnew/v0.24.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ Datetimelike
441441
Timedelta
442442
^^^^^^^^^
443443

444-
-
444+
- Fixed bug where array of timestamp and deltas raised a TypeError: unsupported operand type(s) for -: ``numpy.ndarray`` and ``Timedelta`` (:issue:`21980`)
445445
-
446446
-
447447

pandas/_libs/tslibs/timedeltas.pyx

+9-4
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,15 @@ def _binary_op_method_timedeltalike(op, name):
542542

543543
elif hasattr(other, 'dtype'):
544544
# nd-array like
545-
if other.dtype.kind not in ['m', 'M']:
546-
# raise rathering than letting numpy return wrong answer
545+
try:
546+
if other.dtype.kind in ['m', 'M']:
547+
return op(self.to_timedelta64(), other)
548+
elif other.dtype.kind == 'O':
549+
return np.array([op(self, x) for x in other])
550+
else:
551+
return NotImplemented
552+
except:
547553
return NotImplemented
548-
return op(self.to_timedelta64(), other)
549554

550555
elif not _validate_ops_compat(other):
551556
return NotImplemented
@@ -929,7 +934,7 @@ cdef class _Timedelta(timedelta):
929934
def nanoseconds(self):
930935
"""
931936
Return the number of nanoseconds (n), where 0 <= n < 1 microsecond.
932-
937+
933938
Returns
934939
-------
935940
int

pandas/tests/scalar/timedelta/test_arithmetic.py

+105
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,79 @@ def test_td_rsub_numeric_raises(self):
200200
with pytest.raises(TypeError):
201201
2.0 - td
202202

203+
def test_td_sub_timedelta_timedeltalike_array(self):
204+
# GH 21980
205+
arr = np.array([Timestamp('20130101 9:01'),
206+
Timestamp('20121230 9:02')])
207+
exp = np.array([Timestamp('20121231 9:01'),
208+
Timestamp('20121229 9:02')])
209+
res = arr - pd.Timedelta('1D')
210+
tm.assert_numpy_array_equal(res, exp)
211+
212+
def test_td_sub_timedelta_mixed_timedeltalike_array(self):
213+
# GH 21980
214+
now = pd.Timestamp.now()
215+
arr = np.array([now,
216+
pd.Timedelta('1D')])
217+
exp = np.array([now - pd.Timedelta('1D'),
218+
pd.Timedelta('0D')])
219+
res = arr - pd.Timedelta('1D')
220+
tm.assert_numpy_array_equal(res, exp)
221+
222+
def test_td_rsub_timedelta_timedeltalike_array(self):
223+
# GH 21980
224+
arr = np.array([Timestamp('20130101 9:01'),
225+
Timestamp('20121230 9:02')])
226+
with pytest.raises(TypeError):
227+
# an timedelta - timestamp doesnt make sense
228+
res = pd.Timedelta('1D') - arr
229+
230+
def test_td_rsub_timedelta_mixed_timedeltalike_array(self):
231+
# GH 21980
232+
now = pd.Timestamp.now()
233+
arr = np.array([now,
234+
pd.Timedelta('1D')])
235+
with pytest.raises(TypeError):
236+
# an timedelta - timestamp doesnt make sense
237+
res = pd.Timedelta('1D') - arr
238+
239+
def test_td_add_timedelta_timedeltalike_array(self):
240+
# GH 21980
241+
arr = np.array([Timestamp('20130101 9:01'),
242+
Timestamp('20121230 9:02')])
243+
exp = np.array([Timestamp('20130102 9:01'),
244+
Timestamp('20121231 9:02')])
245+
res = arr + pd.Timedelta('1D')
246+
tm.assert_numpy_array_equal(res, exp)
247+
248+
def test_td_add_timedelta_mixed_timedeltalike_array(self):
249+
# GH 21980
250+
now = pd.Timestamp.now()
251+
arr = np.array([now,
252+
pd.Timedelta('1D')])
253+
exp = np.array([now + pd.Timedelta('1D'),
254+
pd.Timedelta('2D')])
255+
res = arr + pd.Timedelta('1D')
256+
tm.assert_numpy_array_equal(res, exp)
257+
258+
def test_td_radd_timedelta_timedeltalike_array(self):
259+
# GH 21980
260+
arr = np.array([Timestamp('20130101 9:01'),
261+
Timestamp('20121230 9:02')])
262+
exp = np.array([Timestamp('20130102 9:01'),
263+
Timestamp('20121231 9:02')])
264+
res = pd.Timedelta('1D') + arr
265+
tm.assert_numpy_array_equal(res, exp)
266+
267+
def test_td_radd_timedelta_mixed_timedeltalike_array(self):
268+
# GH 21980
269+
now = pd.Timestamp.now()
270+
arr = np.array([now,
271+
pd.Timedelta('1D')])
272+
exp = np.array([now + pd.Timedelta('1D'),
273+
pd.Timedelta('2D')])
274+
res = pd.Timedelta('1D') + arr
275+
tm.assert_numpy_array_equal(res, exp)
203276

204277
class TestTimedeltaMultiplicationDivision(object):
205278
"""
@@ -616,3 +689,35 @@ def test_rdivmod_invalid(self):
616689

617690
with pytest.raises(TypeError):
618691
divmod(np.array([22, 24]), td)
692+
693+
def test_td_div_timedelta_timedeltalike_array(self):
694+
# GH 21980
695+
arr = np.array([Timestamp('20130101 9:01'),
696+
Timestamp('20121230 9:02')])
697+
698+
with pytest.raises(TypeError):
699+
res = arr / pd.Timedelta('1D')
700+
701+
def test_td_rdiv_timedelta_mixed_timedeltalike_array(self):
702+
# GH 21980
703+
arr = np.array([pd.Timestamp.now(),
704+
pd.Timedelta('1D')])
705+
706+
with pytest.raises(TypeError):
707+
res = pd.Timedelta('1D') / arr
708+
709+
def test_td_mult_timedelta_mixed_timedeltalike_array(self):
710+
# GH 21980
711+
arr = np.array([pd.Timestamp.now(),
712+
pd.Timedelta('1D')])
713+
714+
with pytest.raises(TypeError):
715+
res = pd.Timedelta('1D') * arr
716+
717+
def test_td_rmult_timedelta_mixed_timedeltalike_array(self):
718+
# GH 21980
719+
arr = np.array([pd.Timestamp.now(),
720+
pd.Timedelta('1D')])
721+
722+
with pytest.raises(TypeError):
723+
res = arr * pd.Timedelta('1D')

0 commit comments

Comments
 (0)