diff --git a/doc/source/whatsnew/v1.6.0.rst b/doc/source/whatsnew/v1.6.0.rst index 098750aa3a2b2..c432f46ce4a14 100644 --- a/doc/source/whatsnew/v1.6.0.rst +++ b/doc/source/whatsnew/v1.6.0.rst @@ -172,6 +172,8 @@ Datetimelike Timedelta ^^^^^^^^^ - Bug in :func:`to_timedelta` raising error when input has nullable dtype ``Float64`` (:issue:`48796`) +- Bug in :class:`Timedelta` constructor incorrectly raising instead of returning ``NaT`` when given a ``np.timedelta64("nat")`` (:issue:`48898`) +- Bug in :class:`Timedelta` constructor failing to raise when passed both a :class:`Timedelta` object and keywords (e.g. days, seconds) (:issue:`48898`) - Timezones diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index bf22967f615c4..545de31159930 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -1662,10 +1662,16 @@ class Timedelta(_Timedelta): # GH 30543 if pd.Timedelta already passed, return it # check that only value is passed - if isinstance(value, _Timedelta) and unit is None and len(kwargs) == 0: + if isinstance(value, _Timedelta): + # 'unit' is benign in this case, but e.g. days or seconds + # doesn't make sense here. + if len(kwargs): + # GH#48898 + raise ValueError( + "Cannot pass both a Timedelta input and timedelta keyword arguments, got " + f"{list(kwargs.keys())}" + ) return value - elif isinstance(value, _Timedelta): - value = value.value elif isinstance(value, str): if unit is not None: raise ValueError("unit must not be specified if the value is a str") @@ -1679,6 +1685,9 @@ class Timedelta(_Timedelta): elif PyDelta_Check(value): value = convert_to_timedelta64(value, 'ns') elif is_timedelta64_object(value): + if get_timedelta64_value(value) == NPY_NAT: + # i.e. np.timedelta64("NaT") + return NaT value = ensure_td64ns(value) elif is_tick_object(value): value = np.timedelta64(value.nanos, 'ns') diff --git a/pandas/tests/scalar/timedelta/test_constructors.py b/pandas/tests/scalar/timedelta/test_constructors.py index 5b2438ec30f3a..9e1cac4bd2627 100644 --- a/pandas/tests/scalar/timedelta/test_constructors.py +++ b/pandas/tests/scalar/timedelta/test_constructors.py @@ -7,6 +7,7 @@ from pandas._libs.tslibs import OutOfBoundsTimedelta from pandas import ( + NaT, Timedelta, offsets, to_timedelta, @@ -371,6 +372,17 @@ def test_timedelta_constructor_identity(): assert result is expected +def test_timedelta_pass_td_and_kwargs_raises(): + # don't silently ignore the kwargs GH#48898 + td = Timedelta(days=1) + msg = ( + "Cannot pass both a Timedelta input and timedelta keyword arguments, " + r"got \['days'\]" + ) + with pytest.raises(ValueError, match=msg): + Timedelta(td, days=2) + + @pytest.mark.parametrize( "constructor, value, unit, expectation", [ @@ -402,3 +414,9 @@ def test_string_without_numbers(value): ) with pytest.raises(ValueError, match=msg): Timedelta(value) + + +def test_timedelta_new_npnat(): + # GH#48898 + nat = np.timedelta64("NaT", "h") + assert Timedelta(nat) is NaT