timex
timex copied to clipboard
Timex.shift/2 with time-shift always converts precision to :microsecond in Elixir v1.14+
Steps to reproduce
with Elixir v1.13
iex(1)> now = ~U[2023-01-01 10:20:30Z]
~U[2023-01-01 10:20:30Z]
iex(2)> Timex.shift(now, hours: 1)
~U[2023-01-01 11:20:30Z] # OK
with Elixir v1.14
iex(1)> now = ~U[2023-01-01 10:20:30Z]
~U[2023-01-01 10:20:30Z]
iex(2)> Timex.shift(now, hours: 1)
~U[2023-01-01 11:20:30.000000Z] # precision changes unnecessarily
Description of issue
- Elixir v1.14 changes DateTime.add/4 behaviour to preserve the maximum precision of given parameters.
- commit: https://github.com/elixir-lang/elixir/commit/5a583c753b96865a7cdec2fb4c1ab9c96b836d24
- relates to: https://github.com/elixir-lang/elixir/issues/12303
- Timex.shift/2 uses DateTime.add/4 with
:microsecond
precision to apply time-shift result.- https://github.com/bitwalker/timex/blob/e1c4d424a5c7840f63efd33cd70e3b5d4f9bfaa1/lib/datetime/datetime.ex#L450
This causes unnecessary precision conversions in Elixir v1.14 and later.
That change went live in Elixir 1.14.3, so the versions prior to that work fine still.
Same happend to NaiveDatetime, as it converts the NaiveDateTime to DateTime under the hood.
https://github.com/bitwalker/timex/blob/e1c4d424a5c7840f63efd33cd70e3b5d4f9bfaa1/lib/datetime/naivedatetime.ex#L238-L240
It uses the Timex.shift/2
(which operates with DateTime), which leads to the following result:
iex(1)> now = ~N[2023-03-31 10:31:57]
iex(2)> Timex.shift(now, hours: 1)
~N[2023-03-31 11:31:57.000000]
This breaks some of my code (using ecto), with the error "...naive_datetime expects microseconds to be empty...", where just ~N[2023-03-31 10:31:57]
is expected. Is this the supposed behavior in the future?
The intended behaviour is to only add microseconds when subsecond precisions is requested. https://github.com/elixir-lang/elixir/blob/5a583c753b96865a7cdec2fb4c1ab9c96b836d24/lib/elixir/lib/calendar/naive_datetime.ex#L379-L387