Home > Software design >  Converting UTC timestamps to the users time zone in ELM
Converting UTC timestamps to the users time zone in ELM

Time:11-07

I am working on a calendar written im ELM, that needs to show entries it gets from a backend over a REST interface. All times I get from the backend are in UTC, and I need to show them to the user in the user's time zone.

I implemented this by getting the timezone off the user once at the beginning with the following task:

getTimezone : Cmd Msg
getTimezone =
    Task.perform SetTimezone here

and stored the result in the model.

Whenever I needed to show the user a timestamp, I used these two functions:

formatTime : Zone -> Posix -> String
formatTime zone timestamp =
    let
        hour =
            toHour zone timestamp

        minute =
            toMinute zone timestamp
    in
    (padLeft 2 '0' <| fromInt hour)    ":"    (padLeft 2 '0' <| fromInt minute)

formatTimeOfIsoTimestamp : Zone -> String -> String
formatTimeOfIsoTimestamp zone isoTimestamp =
    toTime isoTimestamp |> Result.map (formatTime zone) |> Result.withDefault isoTimestamp

Now that we had the switch from DST to standard time last week end in Europe, I noticed a problem:

Last week (still having DST) all times within this week were off by one hour because my code was still adding two hours (offset for CEST) to the timestamps while only adding one hour (offset for CET) would have been correct. This week it's the opposite: timestamps of this week and the following weeks are correct, while timestamps of the past weeks are now all incorrect.

I have seen the notes in https://package.elm-lang.org/packages/elm/time/latest/Time#here that propably are what I have a problem with: here does not return the timezone Europe/Berlin information but a fixed offset, in my case Etc/GMT 1 or Etc/GMT 2 depending on whether DST is active or not at the moment.

My question now is: how do I correctly handle time zones in ELM, if I need to format timestamps distributed over the complete year? Is there any other package, that can help me with this? If required I could also ask the server for the correct timezone of the user (e.g. Europe/Berlin), but I don't want to make a server request for each timestamp I need to convert for performance reasons. So I think I need some implementation of the IANA time zone database in ELM.

CodePudding user response:

Rather than using the fixed offset that Time.here provides, an alternative is to pass in the result of Intl.DateTimeFormat().resolvedOptions().timeZone (MDN) through the flags at startup.

Using justinmimbs/timezone-data, parsing it on the Elm side may look something like:

TimeZone.zones
    |> Dict.get resolvedTimeZone
    |> Maybe.withDefault TimeZone.zone_australia__sydney
  • Related