From 108ebebcea8bb636cf963d85fb67205fb9efa11d Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 25 Oct 2018 12:28:31 -0700 Subject: [PATCH 1/4] test for multiply by NaN --- pandas/_libs/tslibs/timedeltas.pyx | 8 ++++++++ pandas/tests/scalar/timedelta/test_arithmetic.py | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 7aeff9bec75b5..3fd641e8bede7 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -1062,6 +1062,10 @@ class Timedelta(_Timedelta): return other.delta * self return NotImplemented + elif util._checknan(other): + # i.e. np.nan + return NaT + elif hasattr(other, 'dtype'): # ndarray-like return other * self.to_timedelta64() @@ -1089,6 +1093,10 @@ class Timedelta(_Timedelta): # convert to Timedelta below pass + elif util._checknan(other): + # i.e. np.nan + return NaT + elif hasattr(other, 'dtype'): return self.to_timedelta64() / other diff --git a/pandas/tests/scalar/timedelta/test_arithmetic.py b/pandas/tests/scalar/timedelta/test_arithmetic.py index 179768fcc6709..6d4412cfbefa3 100644 --- a/pandas/tests/scalar/timedelta/test_arithmetic.py +++ b/pandas/tests/scalar/timedelta/test_arithmetic.py @@ -226,6 +226,14 @@ def test_td_mul_nat(self, op, td_nat): with pytest.raises(TypeError): op(td, td_nat) + @pytest.mark.parametrize('nan', [np.nan, np.float64('NaN'), float('nan')]) + @pytest.mark.parametrize('op', [operator.mul, ops.rmul]) + def test_td_mul_nan(self, op, nan): + # np.float64('NaN') has a 'dtype' attr, avoid treating as array + td = Timedelta(10, unit='d') + result = op(td, nan) + assert result is NaT + @pytest.mark.parametrize('op', [operator.mul, ops.rmul]) def test_td_mul_scalar(self, op): # GH#19738 From 00d6c42d9f9ca92d3cdc582294a5f8e9cfe79b98 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 25 Oct 2018 14:36:31 -0700 Subject: [PATCH 2/4] update --- pandas/_libs/tslibs/timedeltas.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 14e412c195b48..aec496f8d8cd6 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -1213,7 +1213,7 @@ class Timedelta(_Timedelta): return other.delta * self return NotImplemented - elif util._checknan(other): + elif util.is_nan(other): # i.e. np.nan return NaT @@ -1244,7 +1244,7 @@ class Timedelta(_Timedelta): # convert to Timedelta below pass - elif util._checknan(other): + elif util.is_nan(other): # i.e. np.nan return NaT From fb8f5e25a2a8109074672b38922625945abb69c3 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 25 Oct 2018 14:41:07 -0700 Subject: [PATCH 3/4] better comment --- pandas/_libs/tslibs/timedeltas.pyx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index aec496f8d8cd6..41925139e41ae 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -1214,7 +1214,9 @@ class Timedelta(_Timedelta): return NotImplemented elif util.is_nan(other): - # i.e. np.nan + # i.e. np.nan, but also catch np.float64("NaN") which would + # otherwise get caught by the hasattr(other, "dtype") branch + # incorrectly return a np.timedelta64 object. return NaT elif hasattr(other, 'dtype'): @@ -1245,7 +1247,9 @@ class Timedelta(_Timedelta): pass elif util.is_nan(other): - # i.e. np.nan + # i.e. np.nan, but also catch np.float64("NaN") which would + # otherwise get caught by the hasattr(other, "dtype") branch + # incorrectly return a np.timedelta64 object. return NaT elif hasattr(other, 'dtype'): From 6588e199b1204923c930d37567dea35e68827a8d Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 25 Oct 2018 14:43:50 -0700 Subject: [PATCH 4/4] add test for div --- pandas/tests/scalar/timedelta/test_arithmetic.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandas/tests/scalar/timedelta/test_arithmetic.py b/pandas/tests/scalar/timedelta/test_arithmetic.py index 6746f06eeb30b..65709b0eebaf7 100644 --- a/pandas/tests/scalar/timedelta/test_arithmetic.py +++ b/pandas/tests/scalar/timedelta/test_arithmetic.py @@ -336,6 +336,16 @@ def test_td_div_numeric_scalar(self): assert isinstance(result, Timedelta) assert result == Timedelta(days=2) + @pytest.mark.parametrize('nan', [np.nan, np.float64('NaN'), float('nan')]) + def test_td_div_nan(self, nan): + # np.float64('NaN') has a 'dtype' attr, avoid treating as array + td = Timedelta(10, unit='d') + result = td / nan + assert result is NaT + + result = td // nan + assert result is NaT + # --------------------------------------------------------------- # Timedelta.__rdiv__