Does Elixir’s DateTime.from_naive/3 support selecting the later offset during ambiguous DST transitions?
0 reputation · 02 Nov 2020, 09:12 UTC
0 reputation · 02 Nov 2020, 09:12 UTC
When converting a naive datetime to an timezone‑aware DateTime in Elixir, the goal is to correctly handle ambiguous times that occur during daylight‑saving‑time fallback transitions without introducing an external dependency such as Timex. The standard DateTime.from_naive/3 function resolves ambiguity by defaulting to the earlier offset and does not expose a way to choose the later offset or to query which offset was applied. This leaves developers uncertain whether the built‑in API can be instructed to select the second occurrence or to retrieve fold information for disambiguation.
Does DateTime.from_naive/3 accept a :fold option to select the later offset? If not, is there any plan to expose fold information in the standard DateTime module?
35275 reputation · 02 Nov 2020, 17:26 UTC
No, DateTime.from_naive/3 does not accept a :fold option. Passing fold: :last raises an ArgumentError for an unknown option. However, the function does support selecting the later offset during ambiguous DST fallback transitions through the :ambiguous option, not :fold.
The :ambiguous option defaults to :first. Setting ambiguous: :last instructs the function to resolve ambiguous local times to the second occurrence, which corresponds to the later UTC offset after clocks fall back.
It is important to distinguish this from the :fold concept used in some other time APIs. Elixir's standard DateTime module does not expose fold metadata in the return value; it returns only {:ok, datetime} or {:error, reason}. You cannot query which offset was applied after the fact.
This behavior is consistent with Elixir 1.16 and 1.17. As of those versions, there is no announced plan to add a :fold option or fold reporting to the standard library.
You can confirm the distinction in IEx using the America/New_York fallback on November 5, 2023, when 01:30 occurs twice:
# Default resolves to the earlier offset
DateTime.from_naive(~N[2023-11-05 01:30:00], "America/New_York")
# => {:ok, ~U[2023-11-05 05:30:00Z]} (UTC-04:00)
# Explicitly select the later offset
DateTime.from_naive(~N[2023-11-05 01:30:00], "America/New_York", ambiguous: :last)
# => {:ok, ~U[2023-11-05 06:30:00Z]} (UTC-05:00)
# :fold is not a recognized option
DateTime.from_naive(~N[2023-11-05 01:30:00], "America/New_York", fold: :last)
# => raises ArgumentError for unknown option :fold
:ambiguous option only affects ambiguous times. Local times skipped during spring-forward transitions still return :invalid unless you pass :raise or :nil.:first without explicit handling can silently produce the earlier offset in user-facing applications.If your application must record which occurrence was chosen, you will need to track that decision in application logic rather than extracting it from the returned DateTime struct.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.