diff --git a/src/humanize/time.py b/src/humanize/time.py index 4a07d528..975cc03c 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -153,6 +153,16 @@ def naturaldelta( delta = dt.timedelta(seconds=value) except (ValueError, TypeError): return str(value) + except OverflowError: + # `int(value)` raises OverflowError for non-finite floats (inf/-inf), + # which, like NaN, are returned unchanged. A too-large *finite* value + # (whose OverflowError comes from `timedelta`) is still raised, per + # the documented `OverflowError` contract. + import math + + if not math.isfinite(value): + return str(value) + raise use_months = months diff --git a/tests/test_time.py b/tests/test_time.py index 76997704..c3743bbc 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -138,6 +138,25 @@ def test_naturaldelta(test_input: float | dt.timedelta, expected: str) -> None: assert humanize.naturaldelta(-test_input) == expected +@pytest.mark.parametrize( + "value, expected", + [ + (float("nan"), "nan"), + (float("inf"), "inf"), + (float("-inf"), "-inf"), + ], +) +def test_naturaldelta_non_finite(value: float, expected: str) -> None: + """Non-finite floats are returned unchanged instead of raising.""" + assert humanize.naturaldelta(value) == expected + + +def test_naturaldelta_too_large_value_raises() -> None: + """A too-large *finite* value still raises OverflowError (unlike inf).""" + with pytest.raises(OverflowError): + humanize.naturaldelta(1e30) + + @freeze_time(FROZEN_DATE) @pytest.mark.parametrize( "test_input, expected",