bitwalker / timex

A complete date/time library for Elixir projects.
https://hexdocs.pm/timex
MIT License
1.75k stars 379 forks source link

to_datetime without time zone no longer converts DateTime to UTC #721

Open shribe opened 2 years ago

shribe commented 2 years ago

Steps to reproduce

Updating some old code, I got bitten by this. In Timex 3.3.0, I could parse a timestamp in a known local time zone as follows:

Timex.parse!("2022-08-02T20:05", "{ISO:Extended}") |> Timex.to_datetime("America/Chicago") |> Time.to_datetime()

Now, in 3.7.8, the second to_datetime call does not change the time zone:

iex(4)> Timex.parse!("2022-08-02T20:05", "{ISO:Extended}") |> Timex.to_datetime("America/Chicago")
#DateTime<2022-08-02 20:05:00-05:00 CDT America/Chicago>
iex(5)> Timex.parse!("2022-08-02T20:05", "{ISO:Extended}") |> Timex.to_datetime("America/Chicago") |> Timex.to_datetime()
#DateTime<2022-08-02 20:05:00-05:00 CDT America/Chicago>

There is a simple workaround:

iex(6)> Timex.parse!("2022-08-02T20:05", "{ISO:Extended}") |> Timex.to_datetime("America/Chicago") |> Timex.to_datetime("Etc/UTC")
~U[2022-08-03 01:05:00Z]

Perhaps it was a deliberate change that to_datetime is a noop when passed an existing DateTime and no time zone argument, but the documentation does not make this clear. Either the old functionality of shifting to UTC needs to be restored, or the documentation needs to clearly cover this exception.

mpinkston commented 11 months ago

This bit me as well with some old code. I'm assuming the intended behavior is to set TZ to UTC only if it isn't explicitly set in the second argument and can't be inferred from the first. But that's different from treating the second argument as having a default value of "Etc/UTC". The docs only say UTC will be used "If no timezone is provided", which is arguably ambiguous.

Of course timezones are already tricky enough as they are, so I'll be avoiding ambiguity in my own code as much as possible from now on. But, some clarification would be appreciated here.