From 68ab81c7f92b26593df161c2d6f6460dcf832d21 Mon Sep 17 00:00:00 2001 From: Ben Nelson Date: Wed, 25 Jul 2018 13:41:55 -0600 Subject: [PATCH] fix raise of TypeError when subtracting timedelta array closes #21980 --- doc/source/whatsnew/v0.24.0.txt | 2 +- pandas/_libs/tslibs/timedeltas.pyx | 13 +++++++++---- pandas/tests/series/test_timeseries.py | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 43e380abd8bb53..fc046e90e8503d 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -441,7 +441,7 @@ Datetimelike Timedelta ^^^^^^^^^ -- +- Fixed bug where array of timestamp and deltas raised a TypeError: unsupported operand type(s) for -: 'numpy.ndarray' and 'Timedelta' (:issue:`21980`) - - diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index f7a6cf0c6dafc2..3cb4f91a284b2e 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -542,10 +542,15 @@ 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 + try: + 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 + except: return NotImplemented - return op(self.to_timedelta64(), other) elif not _validate_ops_compat(other): return NotImplemented @@ -929,7 +934,7 @@ cdef class _Timedelta(timedelta): def nanoseconds(self): """ Return the number of nanoseconds (n), where 0 <= n < 1 microsecond. - + Returns ------- int diff --git a/pandas/tests/series/test_timeseries.py b/pandas/tests/series/test_timeseries.py index 376b4d71f81e8a..8968aa64ebaa69 100644 --- a/pandas/tests/series/test_timeseries.py +++ b/pandas/tests/series/test_timeseries.py @@ -1012,3 +1012,22 @@ def test_get_level_values_box(self): index = MultiIndex(levels=levels, labels=labels) assert isinstance(index.get_level_values(0)[0], Timestamp) + + def test_diff_sub_timedelta(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_diff_sub_timedelta_mixed(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)