diff --git a/src/humanize/time.py b/src/humanize/time.py index 7c4a28eb..3fae6b6c 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -548,9 +548,21 @@ def precisedelta( ``` """ - date, delta = _date_and_delta(value, precise=True) - if date is None: + import datetime as dt + + if value is None: return str(value) + if isinstance(value, dt.datetime): + _date, delta = _date_and_delta(value, precise=True) + else: + try: + delta = abs( + value + if isinstance(value, dt.timedelta) + else dt.timedelta(seconds=value) + ) + except (ValueError, TypeError): + return str(value) suppress_set = {Unit[s.upper()] for s in suppress} @@ -565,9 +577,9 @@ def precisedelta( suppress_set = _suppress_lower_units(min_unit, suppress_set) # handy aliases - days = delta.days - secs = delta.seconds - usecs = delta.microseconds + days: float = delta.days + secs: float = delta.seconds + usecs: float = delta.microseconds MILLISECONDS = Unit.MILLISECONDS SECONDS = Unit.SECONDS diff --git a/tests/test_time.py b/tests/test_time.py index 887a3fc5..7cc631ad 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -838,6 +838,26 @@ def test_precisedelta_suppress_units( ) +@pytest.mark.parametrize( + "value, expected", + [ + (dt.timedelta(days=4_000_000), "4000000 days"), + (dt.timedelta(days=-4_000_000), "4000000 days"), + (4_000_000 * ONE_DAY, "4000000 days"), + (-4_000_000 * ONE_DAY, "4000000 days"), + (dt.timedelta.min, "999999999 days"), + (dt.timedelta.max, "1000000000 days"), + ], +) +def test_precisedelta_beyond_datetime_range( + value: dt.timedelta | float, expected: str +) -> None: + assert ( + humanize.precisedelta(value, minimum_unit="days", suppress=["years", "months"]) + == expected + ) + + def test_precisedelta_bogus_call() -> None: assert humanize.precisedelta(None) == "None"