Skip to content

naturaltime and precisedelta: return non-finite floats unchanged instead of raising OverflowError#344

Open
HrachShah wants to merge 2 commits into
python-humanize:mainfrom
HrachShah:fix/naturaltime-precisedelta-non-finite
Open

naturaltime and precisedelta: return non-finite floats unchanged instead of raising OverflowError#344
HrachShah wants to merge 2 commits into
python-humanize:mainfrom
HrachShah:fix/naturaltime-precisedelta-non-finite

Conversation

@HrachShah

Copy link
Copy Markdown

Both naturaltime() and precisedelta() feed a float input through _date_and_delta(), which passes it straight to round() (or skips rounding when precise=True). For float('inf') and float('-inf'), round() raises OverflowError: cannot convert float infinity to integer and dt.timedelta(seconds=float('inf')) raises the same. The except clause in the function catches ValueError, TypeError, but not OverflowError, so the user gets a traceback rather than the documented "return str(value) unchanged" behavior.

naturaldelta() already had the same bug, fixed in #342 by widening the except to include OverflowError. naturaltime() and precisedelta() still crash because they take a different path (round() instead of int()). This PR mirrors #342's fix for the two other public functions, by guarding the float-input branch with an explicit math.isfinite check before round()/timedelta() and by widening the except to (ValueError, TypeError, OverflowError) so a huge but finite value (e.g. 1e100) falls through the same way.

precise=True (used by precisedelta()) skips the round() call but still constructs dt.timedelta(seconds=value), which raises OverflowError for non-finite floats. The isfinite guard handles both paths.

Verified:

  • python3 -m pytest tests/ -> 724 passed, 69 skipped.
  • 6 new test cases (3 each for naturaltime/precisedelta covering inf/-inf/nan) fail on the pre-fix code with OverflowError: cannot convert float infinity to integer and pass with the fix. 3 additional cases (the NaN parametrizations) pass on both pre-fix and post-fix because round(float('nan')) raises ValueError, which the original except already caught.
  • Sanity check: naturaltime(30) still returns "30 seconds ago", precisedelta(dt.timedelta(days=2, seconds=3633, microseconds=123000)) still returns "2 days, 1 hour and 33.12 seconds".

Zo Bot and others added 2 commits July 4, 2026 23:35
naturaltime and precisedelta both routed their float input through
_date_and_delta, which fed it straight to round() (or skipped round
in precise mode) and then dt.timedelta(seconds=...). For a non-finite
float like inf or -inf, round(float("inf")) raises OverflowError
and dt.timedelta(seconds=float("inf")) raises OverflowError too.
NaN happened to work because round(float("nan")) raises ValueError
which the except clause caught, but inf/-inf slipped past.

The naturaldelta path caught inf/-inf via a different probe (it
calls int(value) first, which raises OverflowError for inf) and
that case is fixed in the still-open PR python-humanize#342 -- this commit leaves
that probe alone and adds the equivalent isfinite guard inside
_date_and_delta, which is what both naturaltime and precisedelta
go through. Adding OverflowError to the except tuple covers the
last remaining case where a finite but oversized number
(> ~3e9 days in seconds) would otherwise crash.

Three new parametrized test functions in tests/test_time.py cover
naturaltime, precisedelta, and the internal _date_and_delta
contract for inf/-inf/nan. The inf and -inf cases fail on the
pre-fix code with OverflowError; the nan case already worked and
is included as a regression guard. Full suite: 724 passed,
69 skipped.
@hugovk

hugovk commented Jul 5, 2026

Copy link
Copy Markdown
Member

There are now four open PRs to fix #333, and one is already an approved: #334.

What's wrong with that PR? What does your PR add or do better?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants