Fix dehumanize() silently ignoring negative time values#1279
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1279 +/- ##
=========================================
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 Sentry. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds an early-rejection check in Arrow.dehumanize so that inputs containing negative numbers (e.g. "in -1 hours") raise ValueError instead of silently producing a wrongly-signed result (issue #1278).
Changes:
- Add a regex check at the start of
dehumanizethat raisesValueErrorwhen the input contains a negative number. - Add a unit test verifying the new behavior across a few representative inputs.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| arrow/arrow.py | Adds the negative-number guard with a descriptive ValueError in dehumanize. |
| tests/test_arrow.py | Adds test_negative_values covering several negative-number inputs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if re.search(r"-\d", input_string): | ||
| raise ValueError( | ||
| f"Negative time values are not supported in dehumanize " | ||
| f"(got {input_string!r}). " | ||
| f"Use a positive value with 'ago' or 'in' to indicate direction." | ||
| ) |
There was a problem hiding this comment.
Thank you for the excellent suggestion! I have refined the regex check to r"(?:^|\s)-\d" so it is anchored to start-of-string or whitespace and won't trigger false positives on hyphen-joined strings in localized non-English timeframes. Pushed the update!
| def test_negative_values(self): | ||
| arw = arrow.Arrow(2000, 6, 18, 5, 55, 0) | ||
|
|
||
| # Negative time values should raise ValueError instead of | ||
| # silently dropping the sign and returning a wrong result. | ||
| # See: https://github.com/arrow-py/arrow/issues/1278 | ||
| negative_inputs = [ | ||
| "in -1 hours", | ||
| "in -2 days", | ||
| "-3 minutes ago", | ||
| "in -30 seconds", | ||
| ] |
There was a problem hiding this comment.
Done! I've added a non-negative test ensuring "in 1 hours" and "2 days ago" succeed, and verified that hyphenated strings without preceding spaces (like "some-2nd-hour") bypass the negative check as expected. Pushed the update!
79847b2 to
aaf224e
Compare
…ning wrong results
aaf224e to
a345b27
Compare
Fixes #1278
Problem
dehumanize("in -1 hours")silently returns the same result asdehumanize("in 1 hours")- it drops the minus sign without any warning.I ran into this while building a scheduling tool that accepts relative time strings from users. A typo like
"in -2 days"would silently schedule something 2 days ahead instead of raising an error, which took me a while to track down.Root cause
The number-extraction regex in
dehumanize()uses\d+to match the numeric value from the input. Since\donly matches[0-9], the minus sign in-1is never captured - the regex matches1and moves on. The sign information is completely lost.Before this fix
After this fix
Changes
arrow/arrow.py: Added an early check indehumanize()that detects negative numbers (-\dpattern) in the input string and raises aValueErrorwith a clear message, before the regex-based parsing begins.tests/test_arrow.py: Addedtest_negative_valuesto verify that inputs like"in -1 hours","in -2 days","-3 minutes ago", and"in -30 seconds"all raiseValueError.All existing dehumanize tests continue to pass.