#1341·arrow

dehumanize() silently returns wrong times for fractional inputs ("1.5 hours ago" is off by 3.5 hours)

Author: MukllerCreated Aug 24, 2026Updated Aug 24, 2026

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.