榆树 0.19.1 中有 4 位数字的当前年份

Current year with 4 digits in elm 0.19.1

如何使用 ELM 0.19.1 实现一个函数来获取 4 位数的当前年份?我已经阅读了一些内容,但对 0.19.1 没有任何作用。

签名:

getCurrentYear : Int

执行:

getCurrentYear => 2020

编辑:

可能正在执行 new Date().getFullYear() javascript 代码?

正如我在评论中所说,不可能在 Elm 中定义 returns 今年的函数。您必须从 Elm 运行时系统中获取此类信息(基本上是 JavaScript,但您不必自己编写)。这是通过 commands, where you tell the runtime system to do something for you. But note that you can't simply retrieve the "return value" of that command and get it back into your Elm code. Instead you have to pass it into a function that can convert it into a "message" (see basic Elm Architecture tutorial here 发生的,在您可以使用 Elm 做任何事情之前理解这一点是最基本的)——这样您就可以将值存储在您的模型中,从而在您的应用程序中显示它。

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

为了具体地获取年份,看起来您需要 this library, which gives you (as now) a Task rather than a Cmd. You can use Task.perform to convert it to a command, which is documented 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 在他的回答中所解释的那样。

最简单的方法是通过 flags when you start the app, since the current year isn't likely to change in the course of the application running. In that case, you can use the snippet of JavaScript you suggested (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 to request the current time, as suggests, however that is pointing to Elm 0.18 documentation (for elm-lang/core instead of elm/time). For 0.19, you need both a Time.Posix and a Time.Zone in order to call Time.toYear. You can chain Time.now (a Task producing a Posix value) and Time.here (a Task producing a Zone with the current time zone offset) to retrieve those values in one Cmd. Here's an example (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) ]