【问题标题】:Current year with 4 digits in elm 0.19.1榆树 0.19.1 中 4 位数字的当前年份
【发布时间】:2020-04-16 20:43:25
【问题描述】:

如何使用 ELM 0.19.1 获取 4 位数字的当前年份?我读过一些东西,但 0.19.1 没有任何作用。

签名:

getCurrentYear : Int

执行:

getCurrentYear => 2020

编辑:

也许正在执行new Date().getFullYear() javascript 代码?

【问题讨论】:

  • 这根本不是纯函数式语言的工作方式。您可以通过 Elm“运行时系统”获取当前日期,但您不能编写在不同时间返回不同值的 Elm 函数。
  • @RobinZigmond 如何通过运行时系统获得年份?
  • 见下面我的回答。不幸的是,没有简单的“只做这个”,但我试图通过有用的链接来解释如何在 Elm 架构中做这种事情。

标签: date elm


【解决方案1】:

最简单的方法是在启动应用程序时通过flags 传递年份,因为当前年份不太可能在应用程序运行过程中发生变化。在这种情况下,您可以使用您建议的 JavaScript 的 sn-p (ellie example):

    Elm.Main.init({ 
      node: document.querySelector('main'), 
      flags: {
        year: new Date().getFullYear(),
      } 
    });
module Main exposing (main)

import Browser
import Html exposing (Html, p, text)


type alias Flags =
    { year : Int }


main : Program Flags Model Msg
main =
    Browser.element
        { init = \flags -> ( Model flags.year, Cmd.none )
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        }


type alias Model =
    { year : Int }


type Msg
    = NoOp


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            ( model, Cmd.none )


view : Model -> Html Msg
view model =
    p [] [ text "The year is ", text (String.fromInt model.year) ]

或者,您可以使用Time.now 来请求当前时间,正如Robin Zigmond's answer 所建议的那样,但这指向Elm 0.18 文档(用于elm-lang/core 而不是elm/time)。对于 0.19,您需要 Time.PosixTime.Zone 才能调用 Time.toYear。您可以链接 Time.nowTask 产生 Posix 值)和 Time.hereTask 产生带有当前时区偏移量的 Zone)以在一个 Cmd 中检索这些值。这是一个示例 (also on ellie)

module Main exposing (main)

import Browser
import Html exposing (Html, p, text)
import Task exposing (Task)
import Time


type alias Flags =
    { year : Int }


main : Program () Model Msg
main =
    Browser.element
        { init = \() -> ( Model 0, whatYearIsIt |> Task.perform GotYear )
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        }


whatYearIsIt : Task x Int
whatYearIsIt =
    Task.map2 Time.toYear Time.here Time.now


type alias Model =
    { year : Int }


type Msg
    = GotYear Int


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotYear year ->
            ( { model | year = year }, Cmd.none )


view : Model -> Html Msg
view model =
    p [] [ text "The year is ", text (String.fromInt model.year) ]

【讨论】:

  • 谢谢,我没有意识到我的文档链接已过期。 (我对 Elm 的一个问题是很难找到最新的文档,尤其是从 0.18 到 0.19 的过渡。)我会更新我自己的答案。
  • 是的,0.19 的过渡很棘手,部分原因是它们从 elm-lang 组织转移到了 elm,所以所有 elm-lang 核心包的“最新”版本仍然存在在 0.18
【解决方案2】:

正如我在评论中已经说过的,不可能在 Elm 中定义一个返回当前年份的函数。您必须从 Elm 运行时系统(基本上是 JavaScript,但您不必自己编写)获取此类信息。这通过commands 发生,您可以在其中告诉运行时系统为您做一些事情。但请注意,您不能简单地检索该命令的“返回值”并将其返回到您的 Elm 代码中。相反,您必须将其传递给一个可以将其转换为“消息”的函数(请参阅基本 Elm 架构教程 here,在您可以使用 Elm 做任何事情之前理解这一点至关重要) - 这样您就可以存储值在您的模型中,从而将其显示在您的应用中。

这些模式确实需要一些时间来了解,特别是如果您不习惯纯函数式编程 - 但是一旦您习惯了它,好处是巨大的,包括几乎可以保证没有运行时错误,以及大大增强的能力推理你的代码。

为了获得具体的年份,您似乎需要this library,它为您(作为now)提供Task,而不是Cmd。您可以使用Task.perform 将其转换为命令,该命令已记录在here - 实际上它甚至提供了一个与您的用例非常匹配的示例 - 我将在此处复制它以供后代使用:

import Time  -- elm install elm/time
import Task

type Msg
  = Click
  | Search String
  | NewTime Time.Posix

getNewTime : Cmd Msg
getNewTime =
  Task.perform NewTime Time.now

您必须填写此内容以适合您自己的用例,尤其是您自己的 Msg 类型。但它给出了一个很好的基本轮廓。要获取用户的当前年份,您需要将Time.Posix 类型替换为Int,并将Time.now 命令替换为(Task.map2 Time.toYear Time.here Time.now),正如@bdukes 在他的回答中所解释的那样。

【讨论】:

  • 有一个更完美的答案吗?
  • 感谢您的回答!图书馆链接显示“NOTE — this package moved to elm/core
  • 抱歉,原来我正在查看的文档已经过时 - Elm 0.19 与 0.18 相比有很多重大变化,因为我实际上并没有那么多使用 Elm,所以我没有意识到我正在看旧的东西。我已经更新了,如果您还有问题,请告诉我。
  • @bkspurgeon 谢谢,我已经看到了足够多的优秀答案,知道这项工作甚至没有进入前 100 名(你可能会添加一个零或两个) - 但我确实做了一个尽我所能解释事情,如果它对 OP 和其他类似问题的人有所帮助,这就是我所希望的。
  • 我非常感谢你,我非常感谢你所做的工作,但其他同事 (@bdukes) 也做了,最后我决定使用标志。对不起
猜你喜欢
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多