From 0bd8d4bb203af185f439c9fcde676e48bd7c6c6f Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 21 Apr 2022 13:53:42 -0700 Subject: [PATCH 1/2] BUG: Timedelta(td64, unit=foo) silent overflow --- doc/source/whatsnew/v1.5.0.rst | 2 ++ pandas/_libs/tslibs/dtypes.pyx | 10 ++++++++++ pandas/_libs/tslibs/timedeltas.pyx | 2 -- .../tests/scalar/timedelta/test_constructors.py | 15 +++++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 9f2bbaa8d5120..ba41cd0e41e08 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -479,6 +479,8 @@ Datetimelike Timedelta ^^^^^^^^^ - Bug in :func:`astype_nansafe` astype("timedelta64[ns]") fails when np.nan is included (:issue:`45798`) +- Bug in constructing a :class:`Timedelta` with a ``np.timedelta64`` object and a ``unit`` sometimes silently overflowing and returning incorrect results instead of raising ``OutOfBoundsTimedelta`` (:issue:`??`) +- Time Zones ^^^^^^^^^^ diff --git a/pandas/_libs/tslibs/dtypes.pyx b/pandas/_libs/tslibs/dtypes.pyx index 8f87bfe0b8c7c..7d055b1cb1049 100644 --- a/pandas/_libs/tslibs/dtypes.pyx +++ b/pandas/_libs/tslibs/dtypes.pyx @@ -277,6 +277,16 @@ cdef str npy_unit_to_abbrev(NPY_DATETIMEUNIT unit): return "M" elif unit == NPY_DATETIMEUNIT.NPY_FR_Y: return "Y" + + # Checks for not-really-supported units go at the end, as we don't expect + # to see these often + elif unit == NPY_DATETIMEUNIT.NPY_FR_ps: + return "ps" + elif unit == NPY_DATETIMEUNIT.NPY_FR_fs: + return "fs" + elif unit == NPY_DATETIMEUNIT.NPY_FR_as: + return "as" + else: raise NotImplementedError(unit) diff --git a/pandas/_libs/tslibs/timedeltas.pyx b/pandas/_libs/tslibs/timedeltas.pyx index 6606158aea807..39a3414ca5167 100644 --- a/pandas/_libs/tslibs/timedeltas.pyx +++ b/pandas/_libs/tslibs/timedeltas.pyx @@ -1487,8 +1487,6 @@ class Timedelta(_Timedelta): elif PyDelta_Check(value): value = convert_to_timedelta64(value, 'ns') elif is_timedelta64_object(value): - if unit is not None: - value = value.astype(f'timedelta64[{unit}]') 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 34b725eb9fe77..4357b311d1c9f 100644 --- a/pandas/tests/scalar/timedelta/test_constructors.py +++ b/pandas/tests/scalar/timedelta/test_constructors.py @@ -13,6 +13,21 @@ ) +def test_construct_from_td64_with_unit(): + # ignore the unit, as it may cause silently overflows leading to incorrect + # results, and in non-overflow cases is irrelevant + obj = np.timedelta64(123456789, "h") + + with pytest.raises(OutOfBoundsTimedelta, match="123456789 hours"): + Timedelta(obj, unit="ps") + + with pytest.raises(OutOfBoundsTimedelta, match="123456789 hours"): + Timedelta(obj, unit="ns") + + with pytest.raises(OutOfBoundsTimedelta, match="123456789 hours"): + Timedelta(obj) + + def test_construction(): expected = np.timedelta64(10, "D").astype("m8[ns]").view("i8") assert Timedelta(10, unit="d").value == expected From 69cffccc3d1f1e7121657d07dc1b185c171de7d4 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 21 Apr 2022 13:55:09 -0700 Subject: [PATCH 2/2] GH ref --- doc/source/whatsnew/v1.5.0.rst | 2 +- pandas/tests/scalar/timedelta/test_constructors.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index ba41cd0e41e08..5386e10c695c7 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -479,7 +479,7 @@ Datetimelike Timedelta ^^^^^^^^^ - Bug in :func:`astype_nansafe` astype("timedelta64[ns]") fails when np.nan is included (:issue:`45798`) -- Bug in constructing a :class:`Timedelta` with a ``np.timedelta64`` object and a ``unit`` sometimes silently overflowing and returning incorrect results instead of raising ``OutOfBoundsTimedelta`` (:issue:`??`) +- Bug in constructing a :class:`Timedelta` with a ``np.timedelta64`` object and a ``unit`` sometimes silently overflowing and returning incorrect results instead of raising ``OutOfBoundsTimedelta`` (:issue:`46827`) - Time Zones diff --git a/pandas/tests/scalar/timedelta/test_constructors.py b/pandas/tests/scalar/timedelta/test_constructors.py index 4357b311d1c9f..7fc7bd3a5a74d 100644 --- a/pandas/tests/scalar/timedelta/test_constructors.py +++ b/pandas/tests/scalar/timedelta/test_constructors.py @@ -15,7 +15,7 @@ def test_construct_from_td64_with_unit(): # ignore the unit, as it may cause silently overflows leading to incorrect - # results, and in non-overflow cases is irrelevant + # results, and in non-overflow cases is irrelevant GH#46827 obj = np.timedelta64(123456789, "h") with pytest.raises(OutOfBoundsTimedelta, match="123456789 hours"):