timex icon indicating copy to clipboard operation
timex copied to clipboard

Timex.shift/2 with time-shift always converts precision to :microsecond in Elixir v1.14+

Open enerick opened this issue 2 years ago • 2 comments

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.

enerick avatar Jan 17 '23 03:01 enerick

That change went live in Elixir 1.14.3, so the versions prior to that work fine still.

aniravi24 avatar Jan 23 '23 04:01 aniravi24

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

railsmechanic avatar Mar 30 '23 08:03 railsmechanic