dehumanize() silently returns wrong times for fractional inputs ("1.5 hours ago" is off by 3.5 hours)
- Dominant language
- Python
- Stars
- 9.1k
- Forks
- 784
- PR merge metrics
- No merged PRs in 30d
Description
`dehumanize()` silently returns **wrong times** for any fractional input — the digits around the decimal point are handled independently instead of being parsed as one number.
**Version:** arrow 1.4.0 (release; also on current master). Verified on Python 3.13.
## Repro
```python
import arrow
base = arrow.get("2026-01-01T00:00:00+00:00")
print(base.dehumanize("1.5 hours ago"))
print(base.dehumanize("0.5 days ago"))
```
Actual vs expected:
| input | release 1.4.0 | correct |
|---|---|---|
| `"1.5 hours ago"` | `2025-12-31T19:00:00+00:00` (**−5 h**) | `2025-12-31T22:30:00+00:00` (−1.5 h) |
| `"0.5 days ago"` | `2025-12-27T00:00:00+00:00` (**−5 days**) | `2025-12-31T12:00:00+00:00` (−0.5 d) |
No exception, no warning — just a quietly wrong timestamp, off by 3.5 hours / 4.5 days respectively in these examples. The magnitude of the error scales with the discarded fraction's digits, so inputs like `"2.25 weeks"` drift even further.
## Root cause
The token/number handling in `DateTimeParser.parse` + `dehumanize` ends up splitting `"1.5"` at the dot and treating the fragments as separate numeric contributions rather than one float (`"0.5 days"` behaves like `"5 days"`, which matches the −5 d result exactly).
## Proposed fix direction
Accept an unsigned int-or-decimal in the number pattern fed to dehumanize (e.g. `\d+(?:[.,]\d+)?`, also covering comma decimals used by locales such as fr_FR), convert with `float(...)`, and carry the value through `time_object_info` as float — the downstream `timedelta` math already handles floats.
## Working implementation
PR #1334 implements exactly this and I verified it locally against the matrix above — all cases become exact (`−1.5 h`, `−0.5 d`, and `"1.5 days ago"` → −36 h), including comma-decimal inputs. Filing this issue so the released-version bug is tracked independently of that PR, since users on 1.4.0 are affected today.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with DateTimeParser.parse and dehumanize, then compare the behavior and test coverage in PR #1334. Done means the reported integer, decimal-point, and comma-decimal examples produce the expected timestamps without warnings or exceptions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100