将 UTC 时间戳转换为 ELM 中的用户时区

Converting UTC timestamps to the users time zone in ELM

我正在处理一个用 ELM 编写的日历,它需要显示它通过 REST 接口从后端获取的条目。我从后端得到的所有时间都是UTC时间,我需要在用户的时区显示给用户。

我通过以下任务在开始时让用户关闭时区来实现这一点:

getTimezone : Cmd Msg
getTimezone =
    Task.perform SetTimezone here

并将结果存储在模型中。

每当我需要向用户显示时间戳时,我都会使用这两个函数:

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

既然我们在上周结束时在欧洲从 DST 切换到标准时间,我注意到一个问题:

上周(仍然有夏令时)本周内的所有时间都关闭了一个小时,因为我的代码仍在向时间戳添加两个小时(CEST 的偏移量),而只添加一个小时(CET 的偏移量)会是正确的。本周情况正好相反:本周和接下来几周的时间戳都是正确的,而过去几周的时间戳现在都不正确。

我看到了 https://package.elm-lang.org/packages/elm/time/latest/Time#here 中的注释,这可能是我遇到的问题:here 没有 return 时区 Europe/Berlin 信息,而是一个固定的偏移量,在我的例子中 Etc/GMT+1Etc/GMT+2 取决于 DST 目前是否处于活动状态。

我现在的问题是:如果我需要格式化全年分布的时间戳,我该如何正确处理 ELM 中的时区?有没有其他包可以帮助我解决这个问题?如果需要,我还可以向服务器询问用户的正确时区(例如 Europe/Berlin),但出于性能原因,我不想为我需要转换的每个时间戳发出服务器请求。所以我想我需要在 ELM 中实现 IANA 时区数据库。

与其使用 Time.here 提供的固定偏移量,另一种方法是在启动时传入 Intl.DateTimeFormat().resolvedOptions().timeZone 的结果(MDN) through the flags

使用 justinmimbs/timezone-data,在 Elm 端解析它可能类似于:

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