Skip to content

Commit

Permalink
fix raise of TypeError when subtracting timedelta array
Browse files Browse the repository at this point in the history
closes #21980
  • Loading branch information
illegalnumbers committed Sep 4, 2018
1 parent a5fe9cf commit 9a1bd6f
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 4 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.24.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ Timedelta
- Bug in multiplying a :class:`Series` with numeric dtype against a ``timedelta`` object (:issue:`22390`)
- Bug in :class:`Series` with numeric dtype when adding or subtracting an an array or ``Series`` with ``timedelta64`` dtype (:issue:`22390`)
- Bug in :class:`Index` with numeric dtype when multiplying or dividing an array with dtype ``timedelta64`` (:issue:`22390`)
-
- Fixed bug where subtracting :class:`Timedelta` from an object-dtyped array would raise ``TypeError`` (:issue:`21980`)
-
-

Expand Down
8 changes: 5 additions & 3 deletions pandas/_libs/tslibs/timedeltas.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -541,10 +541,12 @@ def _binary_op_method_timedeltalike(op, name):

elif hasattr(other, 'dtype'):
# nd-array like
if other.dtype.kind not in ['m', 'M']:
# raise rathering than letting numpy return wrong answer
if other.dtype.kind in ['m', 'M']:
return op(self.to_timedelta64(), other)
elif other.dtype.kind == 'O':
return np.array([op(self, x) for x in other])
else:
return NotImplemented
return op(self.to_timedelta64(), other)

elif not _validate_ops_compat(other):
return NotImplemented
Expand Down
118 changes: 118 additions & 0 deletions pandas/tests/scalar/timedelta/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,92 @@ def test_td_rsub_numeric_raises(self):
with pytest.raises(TypeError):
2.0 - td

def test_td_sub_timedeltalike_object_dtype_array(self):
# GH 21980
arr = np.array([Timestamp('20130101 9:01'),
Timestamp('20121230 9:02')])
exp = np.array([Timestamp('20121231 9:01'),
Timestamp('20121229 9:02')])
res = arr - pd.Timedelta('1D')
tm.assert_numpy_array_equal(res, exp)

def test_td_sub_mixed_timedeltalike_object_dtype_array(self):
# GH 21980
now = pd.Timestamp.now()
arr = np.array([now,
pd.Timedelta('1D')])
exp = np.array([now - pd.Timedelta('1D'),
pd.Timedelta('0D')])
res = arr - pd.Timedelta('1D')
tm.assert_numpy_array_equal(res, exp)

def test_td_sub_mixed_most_timedeltalike_object_dtype_array(self):
# GH 21980
now = pd.Timestamp.now()
arr = np.array([now,
pd.Timedelta('1D'),
np.timedelta64(2, 'h')])
exp = np.array([now - pd.Timedelta('1D'),
pd.Timedelta('0D'),
np.timedelta64(2, 'h') - pd.Timedelta('1D')])
res = arr - pd.Timedelta('1D')
tm.assert_numpy_array_equal(res, exp)

def test_td_rsub_timedeltalike_object_dtype_array(self):
# GH 21980
arr = np.array([Timestamp('20130101 9:01'),
Timestamp('20121230 9:02')])
with pytest.raises(TypeError):
# an timedelta - timestamp doesnt make sense
pd.Timedelta('1D') - arr

def test_td_rsub_mixed_timedeltalike_object_dtype_array(self):
# GH 21980
now = pd.Timestamp.now()
arr = np.array([now,
pd.Timedelta('1D')])
with pytest.raises(TypeError):
# an timedelta - timestamp doesnt make sense
pd.Timedelta('1D') - arr

def test_td_add_timedeltalike_object_dtype_array(self):
# GH 21980
arr = np.array([Timestamp('20130101 9:01'),
Timestamp('20121230 9:02')])
exp = np.array([Timestamp('20130102 9:01'),
Timestamp('20121231 9:02')])
res = arr + pd.Timedelta('1D')
tm.assert_numpy_array_equal(res, exp)

def test_td_add_mixed_timedeltalike_object_dtype_array(self):
# GH 21980
now = pd.Timestamp.now()
arr = np.array([now,
pd.Timedelta('1D')])
exp = np.array([now + pd.Timedelta('1D'),
pd.Timedelta('2D')])
res = arr + pd.Timedelta('1D')
tm.assert_numpy_array_equal(res, exp)

def test_td_radd_timedeltalike_object_dtype_array(self):
# GH 21980
arr = np.array([Timestamp('20130101 9:01'),
Timestamp('20121230 9:02')])
exp = np.array([Timestamp('20130102 9:01'),
Timestamp('20121231 9:02')])
res = pd.Timedelta('1D') + arr
tm.assert_numpy_array_equal(res, exp)

def test_td_radd_mixed_timedeltalike_object_dtype_array(self):
# GH 21980
now = pd.Timestamp.now()
arr = np.array([now,
pd.Timedelta('1D')])
exp = np.array([now + pd.Timedelta('1D'),
pd.Timedelta('2D')])
res = pd.Timedelta('1D') + arr
tm.assert_numpy_array_equal(res, exp)


class TestTimedeltaMultiplicationDivision(object):
"""
Expand Down Expand Up @@ -616,3 +702,35 @@ def test_rdivmod_invalid(self):

with pytest.raises(TypeError):
divmod(np.array([22, 24]), td)

def test_td_div_timedelta_timedeltalike_array(self):
# GH 21980
arr = np.array([Timestamp('20130101 9:01'),
Timestamp('20121230 9:02')])

with pytest.raises(TypeError):
arr / pd.Timedelta('1D')

def test_td_rdiv_timedelta_mixed_timedeltalike_array(self):
# GH 21980
arr = np.array([pd.Timestamp.now(),
pd.Timedelta('1D')])

with pytest.raises(TypeError):
pd.Timedelta('1D') / arr

def test_td_mult_timedelta_mixed_timedeltalike_array(self):
# GH 21980
arr = np.array([pd.Timestamp.now(),
pd.Timedelta('1D')])

with pytest.raises(TypeError):
pd.Timedelta('1D') * arr

def test_td_rmult_timedelta_mixed_timedeltalike_array(self):
# GH 21980
arr = np.array([pd.Timestamp.now(),
pd.Timedelta('1D')])

with pytest.raises(TypeError):
arr * pd.Timedelta('1D')

0 comments on commit 9a1bd6f

Please sign in to comment.