From b93d9e1b8504fdab4f5c83de3f14cfbd5293035c Mon Sep 17 00:00:00 2001 From: tamsk-91 <340929521+tamsk-91@users.noreply.github.com> Date: Sun, 25 Oct 2026 10:19:15 +0200 Subject: [PATCH 1/3] Fix OverflowError for far-future dates --- ...t.timedelta(days=365 + 35), \"1 year, 1 month ago\")," | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename src/humanize/time.py => "src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," (98%) diff --git a/src/humanize/time.py "b/src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," similarity index 98% rename from src/humanize/time.py rename to "src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," index 7c4a28eb..a14f5250 100644 --- a/src/humanize/time.py +++ "b/src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," @@ -61,10 +61,10 @@ def _abs_timedelta(delta: dt.timedelta) -> dt.timedelta: Returns: datetime.timedelta: Absolute timedelta. """ - if delta.days < 0: - now = _now() - return now - (now + delta) - return delta + # Use abs() rather than round-tripping through the current datetime: + # `now + delta` overflows (OverflowError) when a negative delta reaches back + # past year 1, e.g. for naturaltime(dt.datetime(9999, 12, 31)). + return abs(delta) def _date_and_delta( From cc020abd43a50d56f1c280183bf64568f1d88beb Mon Sep 17 00:00:00 2001 From: tamsk-91 <340929521+tamsk-91@users.noreply.github.com> Date: Sun, 25 Oct 2026 10:22:44 +0200 Subject: [PATCH 2/3] Add regression tests for far-future overflow --- tests/test_time.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_time.py b/tests/test_time.py index 887a3fc5..c483e669 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -196,6 +196,9 @@ def test_naturaldelta_too_large_value_raises() -> None: (NOW - dt.timedelta(days=365 + 35), "1 year, 1 month ago"), (dt.timedelta(days=-10000), "27 years from now"), (dt.timedelta(days=365 + 35), "1 year, 1 month ago"), + # far-future values used to raise OverflowError in _abs_timedelta + (dt.datetime(9999, 12, 31), "7,995 years from now"), + (dt.timedelta(days=-800_000), "2,192 years from now"), (22.5, "22 seconds ago"), (23.5, "24 seconds ago"), (23.9, "24 seconds ago"), @@ -645,6 +648,12 @@ def test_precisedelta_one_unit_enough( (dt.timedelta(days=32), "seconds", "1 month and 1 day"), (dt.timedelta(days=62), "seconds", "2 months and 1 day"), (dt.timedelta(days=92), "seconds", "3 months"), + # a negative delta reaching back past year 1 used to raise OverflowError + ( + dt.timedelta(days=-800_000), + "seconds", + "2,191 years, 9 months and 10 days", + ), (dt.timedelta(days=31), "days", "1 month"), (dt.timedelta(days=32), "days", "1 month and 1 day"), (dt.timedelta(days=62), "days", "2 months and 1 day"), From 0a607ed1578335408d0847c6e182e634b93facf2 Mon Sep 17 00:00:00 2001 From: tamsk-91 <340929521+tamsk-91@users.noreply.github.com> Date: Sun, 25 Oct 2026 10:27:09 +0200 Subject: [PATCH 3/3] Restore time.py filename --- .../humanize/time.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," => src/humanize/time.py (100%) diff --git "a/src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," b/src/humanize/time.py similarity index 100% rename from "src/humanize/ (dt.timedelta(days=365 + 35), \"1 year, 1 month ago\")," rename to src/humanize/time.py