The Wire · Showcase
ELIXIR FIXES TIME MATH BUG THAT ROUNDS THE WRONG WAY
By RepoJournal · Filed · About Elixir & Phoenix
NaiveDateTime.diff/3 has been silently rounding elapsed time up instead of down, breaking its documented contract and potentially causing logic errors in any code relying on time-based calculations.
The culprit: NaiveDateTime.diff/3 was truncating each operand separately before subtracting, computing floor(t1) - floor(t2) instead of floor(t1 - t2) [1]. When the subtrahend's fractional seconds exceeded the minuend's, this flipped the rounding direction entirely. An elapsed span of 86399.5 seconds (less than one day) incorrectly returned 1 for :day. This fix restores the documented guarantee that fractional results are truncated, not rounded up. Meanwhile, Duration.from_iso8601/1 was accepting malformed ISO 8601 strings with duplicate S markers for seconds [2], a parsing bug now corrected. On the spec side, Registry.lock/3 gains its missing type signature [3], and List specs are tightened to match their actual input handling [4]. These are the kind of quiet correctness fixes that ship before someone's calendar math breaks in production.
Action items
- → Review any code using NaiveDateTime.diff/3 with :day or larger units for rounding assumptions elixir-lang/elixir [plan]
- → Update Elixir when the next patch drops to get these fixes elixir-lang/elixir [plan]
- → Check if you're parsing ISO 8601 durations; Duration.from_iso8601/1 now rejects duplicate S markers elixir-lang/elixir [monitor]
References
- [1] Fix `NaiveDateTime.diff/3` over-counting incomplete units ↗ elixir-lang/elixir
- [2] Fix Duration.from_iso8601/1 accepting duplicate S (secs) when fractional elixir-lang/elixir
- [3] Add spec to Registry.lock/3 (#15575) elixir-lang/elixir
- [4] Fix List specs that are broader than the inputs handled (#15571) elixir-lang/elixir