When calling for example to_iso8601/2 to convert a DateTime to a string, seconds will not be printed if there are seconds in the offset.
For example for Africa/Abidjan: 1911-12-31T00:00:00-00:16:08
Elixir will print it as: 1911-12-31T00:00:00-00:16 and lose information.
In the DateTime module the following function is used to print the offset:
format_offset(total, hour, minute, :extended)
we see that seconds are not taken into account.
(Note that Java prints the offset -00:16:08, as second are present)
I couldn't reproduce this:
iex> ~N[1911-12-31T11:22:33] |> DateTime.from_naive!("Africa/Abidjan", Tzdata.TimeZoneDatabase) |> DateTime.to_string()
"1911-12-31 11:22:33-00:16 LMT Africa/Abidjan"
the seconds are preserved.
Regarding
1911-12-31T00:00:00-00:16:08
I believe the offset -00:16:08 is incorrect per https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
The UTC offset is appended to the time in the same way that 'Z' was above, in the form ±[hh]:[mm], ±[hh][mm], or ±[hh].
and not hh:mm:ss.
The ISO 2016 specification says:
When it is required to indicate local time and the difference between the time scale of local time and UTC, the representation of the difference shall be appended to the representation of the local time following immediately, without space, the lowest order (extreme right-hand) time element of the local time expression. The difference between the time scale of local time and UTC shall be expressed in hours-and-minutes, or hours-only independent of the accuracy of the local time expression associated with it.
The complete representation of the time of 27 minutes and 46 seconds past 15 hours locally in Geneva (in winter one hour ahead of UTC), and in New York (in winter five hours behind UTC), together with the indication of the difference between the time scale of local time and UTC, are used as examples.
Basic format: hhmmss±hhmm hhmmss±hh
Example:
152746+0100
152746−0500
152746+01
152746−05
Extended format: hh:mm:ss±hh:mm hh:mm:ss±hh
Example:
15:27:46+01:00
15:27:46−05:00
15:27:46+01
15:27:46−05
So according to the ISO spec, we shall not include seconds in offsets. I cannot speak if Java or IANA are truly compliant with ISO, but the spec unfortunately does not support the precision you expect. In this case, I believe it is best to roll your custom to_string function.
@kipcole9 do you know if there is any part of ISO or the more recent revisions that support seconds on offsets?
Checked just out of curiosity, both latest php and momentjs do not display the seconds in the offset.
Feels like it's wrong though and that the spec is incomplete, not taking into account those cases; I prefer Java's output even though it probably doesn't follow the spec. Anyway, as I see that other platforms stick strictly with the spec, now I'm thinking that it's not worth to update Elixir for it.
Exactly. It is annoying the spec doesn't handle it but at the same time the reason why we follow the spec is exactly so we don't make these decisions in isolation. We will keep this open for a bit to see if ISO 2019 does support seconds in offsets but, if it does not, then I agree it is best to mark this as unresolved.
I think in UTC are no seconds defined for the UTC-offset, and the IANA DB contains just UTC-offsets with seconds for time zones before 1972. But the ISO standard only assumes UTC and therefore ignores the seconds in UTC offset.
I have found the following line in the IANA files:
In 1972 Liberia was the last country to switch from a UT offset that was not a multiple of 15 or 20 minutes.
Thanks everyone. We will go ahead and close this issue then for the reasons above.