diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 0f18a1fd81815..18123efe76b1d 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -213,6 +213,7 @@ Timedelta ^^^^^^^^^ - Bug in constructing a :class:`Timedelta` with a high precision integer that would round the :class:`Timedelta` components (:issue:`31354`) +- Bug in dividing ``np.nan`` or ``None`` by :class:`Timedelta`` incorrectly returning ``NaT`` (:issue:`31869`) - Timezones diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 66660c5f641fd..298028227e18b 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -1407,7 +1407,14 @@ class Timedelta(_Timedelta): # convert to Timedelta below pass + elif util.is_nan(other): + # i.e. np.nan or np.float64("NaN") + raise TypeError("Cannot divide float by Timedelta") + elif hasattr(other, 'dtype'): + if other.dtype.kind == "O": + # GH#31869 + return np.array([x / self for x in other]) return other / self.to_timedelta64() elif not _validate_ops_compat(other): @@ -1415,7 +1422,8 @@ class Timedelta(_Timedelta): other = Timedelta(other) if other is NaT: - return NaT + # In this context we treat NaT as timedelta-like + return np.nan return float(other.value) / self.value def __floordiv__(self, other): diff --git a/pandas/tests/scalar/timedelta/test_arithmetic.py b/pandas/tests/scalar/timedelta/test_arithmetic.py index 230a14aeec60a..ea02a76275443 100644 --- a/pandas/tests/scalar/timedelta/test_arithmetic.py +++ b/pandas/tests/scalar/timedelta/test_arithmetic.py @@ -412,6 +412,46 @@ def test_td_rdiv_timedeltalike_scalar(self): assert np.timedelta64(60, "h") / td == 0.25 + def test_td_rdiv_na_scalar(self): + # GH#31869 None gets cast to NaT + td = Timedelta(10, unit="d") + + result = NaT / td + assert np.isnan(result) + + result = None / td + assert np.isnan(result) + + result = np.timedelta64("NaT") / td + assert np.isnan(result) + + with pytest.raises(TypeError, match="cannot use operands with types dtype"): + np.datetime64("NaT") / td + + with pytest.raises(TypeError, match="Cannot divide float by Timedelta"): + np.nan / td + + def test_td_rdiv_ndarray(self): + td = Timedelta(10, unit="d") + + arr = np.array([td], dtype=object) + result = arr / td + expected = np.array([1], dtype=np.float64) + tm.assert_numpy_array_equal(result, expected) + + arr = np.array([None]) + result = arr / td + expected = np.array([np.nan]) + tm.assert_numpy_array_equal(result, expected) + + arr = np.array([np.nan], dtype=object) + with pytest.raises(TypeError, match="Cannot divide float by Timedelta"): + arr / td + + arr = np.array([np.nan], dtype=np.float64) + with pytest.raises(TypeError, match="cannot use operands with types dtype"): + arr / td + # --------------------------------------------------------------- # Timedelta.__floordiv__