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
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.
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
Actual vs expected:
"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+dehumanizeends 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 withfloat(...), and carry the value throughtime_object_infoas float — the downstreamtimedeltamath 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.