Skip to content

Reject negative numbers in dehumanize()#1310

Open
eeshsaxena wants to merge 1 commit into
arrow-py:masterfrom
eeshsaxena:fix-dehumanize-negative
Open

Reject negative numbers in dehumanize()#1310
eeshsaxena wants to merge 1 commit into
arrow-py:masterfrom
eeshsaxena:fix-dehumanize-negative

Conversation

@eeshsaxena

Copy link
Copy Markdown

Summary

Fixes #1278.

dehumanize() extracts numbers with an unsigned \d+ pattern, and the surrounding match anchors on a word boundary, so a minus sign attached to a number (e.g. "in -1 hours") is silently discarded. The result is a datetime in the opposite direction from what the string expressed.

Before

>>> now = arrow.now()
>>> (now.dehumanize("in 1 hours")  - now).total_seconds()
3600.0
>>> (now.dehumanize("in -1 hours") - now).total_seconds()
3600.0   # <- same as +1, the minus was dropped

After

>>> now.dehumanize("in -1 hours")
ValueError: Invalid input string: 'in -1 hours'. Negative numbers are not supported; use 'ago' or 'in' to indicate direction.

Rationale

Humanized strings encode direction with words ("ago"/"in"), never with an arithmetic sign, so humanize() itself never emits one. A negative number in the input is therefore always malformed, and returning a quietly-wrong result is worse than raising. The guard rejects any -<digit> in the input; all existing positive/ago/in/now inputs are unaffected.

Tests

Added test_negative_number (covers "in -1 hours", "in -2 days", "-3 minutes ago"). Full dehumanize suite passes (23 tests).

dehumanize() extracts numbers with an unsigned `\d+` pattern, and the
surrounding match anchors on a word boundary, so a minus sign attached
to a number (e.g. "in -1 hours") is silently discarded. The result was
a datetime in the opposite direction from what the string expressed:
"in -1 hours" produced the same value as "in 1 hours".

Humanized strings encode direction with words ("ago"/"in"), never with
an arithmetic sign, so humanize() never emits one. Reject any input
containing a negative number with a ValueError instead of returning a
quietly wrong result.

Fixes arrow-py#1278
@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (2224255) to head (baa58ee).

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #1310   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           10        10           
  Lines         2315      2317    +2     
  Branches       358       359    +1     
=========================================
+ Hits          2315      2317    +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

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.

dehumanize() silently ignores negative time values, returning wrong results

1 participant