我如何获得 Elm 的当前时间?

How do I get the current time in Elm?

我是 运行 elm-repl 来玩弄这门语言。

我想看看现在几点。我该怎么做?目前的图书馆似乎不可能。这是为什么?


编辑:我做了一个包来帮助解决这个问题。 http://package.elm-lang.org/packages/z5h/time-app

这是在 elm 0.15 左右被问到的 - elm 0.17 和 0.18 中的情况有所不同:请参阅

您可以使用 the Time package and/or the Date package.

这是一个同时使用两者的人为示例:

import Signal
import Time exposing (every, second)
import Date exposing (year, hour, minute, second, fromTime)
import Graphics.Element exposing (show)

main =
  Signal.map currentTime (Time.every Time.second)

currentTime t =
  let date' = fromTime t
      hour' = toString (Date.hour date')
      minute' = toString (Date.minute date')
      second' = toString (Date.second date')
      year' = toString (year date')
      now = "The current time is: " ++ hour' ++ ":" ++ minute' ++ ":" ++ second'
  in 
      show now

您可以参阅 了解如何在 Elm 中使用当前时间执行某些操作。

elm-repl 无法使用 Signal 和时间 "changes over time",所以这是一个信号。 据我所知,也没有用于获取时间的 Task。也不是在 repl 中执行任务的方法,尽管我希望将来会有这种功能。

如果您想要程序开始时的时间,您可以执行以下操作:

Now.elm

module Now where

import Native.Now

loadTime : Float
loadTime = Native.Now.loadTime

Native/Now.js

Elm.Native.Now = {};

Elm.Native.Now.make = function(localRuntime) {

  localRuntime.Native = localRuntime.Native || {};


  localRuntime.Native.Now = localRuntime.Native.Now || {};

  if (localRuntime.Native.Now.values) {
    return localRuntime.Native.Now.values;
  }

  var Result = Elm.Result.make(localRuntime);

  return localRuntime.Native.Now.values = {
    loadTime: (new window.Date).getTime()
  };

};

您的代码

programStart = Now.loadTime

为了解决我自己的问题,我创建了 StartApp 的一个变体,其中包含每个操作的时间戳。
所以更新函数有签名:
update : action -> Time -> model -> (model, Effects action)

要点在这里。 https://gist.github.com/z5h/41ca436679591b6c3e51

我可以想到两种在 Elm 中处理当前时间的主要方法:

  1. 编写/使用本机模块来制作一个函数,该函数 returns 当前时间(以毫秒为单位)(或 returns 将执行相同操作的任务)。一般不推荐这种方法。我认为#2 是更好的方法。但是可以在此处找到 #1 的示例:https://github.com/evancz/task-tutorial/blob/1.0.2/src/TaskTutorial.elm(请参阅 getCurrentTime 函数)

  2. 使用 Elm 应用程序架构(https://github.com/evancz/elm-architecture-tutorial/)编写程序,然后将当前时间信号作为更新周期的输入,用新的当前时间更新模型您选择的每个间隔。然后所有其他方法都可以从模型中同步获取当前时间。

0.19 更新 使用标准库无法获取当前时间。您需要使用 elm/time。与 0.18 一样,您只需要一个命令和 Msg 来处理结果

type Msg
    = OnTime Time.Posix 

getTime : Cmd Msg
getTime = 
    Task.perform OnTime Time.now 

0.18 更新 这又变得简单了。现在你只需要一个命令和消息来处理结果

type Msg
    = OnTime Time 

getTime : Cmd Msg
getTime = 
    Task.perform OnTime Time.now 

看到这个Ellie

原回答

有了 0.17,这变得容易多了。 Time library 中现在有一个任务。例如,我们现在有:

Time.now
|> Task.Perform NoOp CurrentTime

Simon H 的回答(0.18)让我开始了正确的方向,但我确实在想出如何在那段时间真正做某事时遇到了一些麻烦。 (user2167582 向 Simon 的回答添加评论,问同样的问题:你好 'get the time out?')。

我的具体问题是我想将当前时间包含在服务器的 POST 正文中。

我最终解决了这个问题并对最终结果感到非常满意——使用 Task.andThen 意味着我在我的 postTime 函数中我可以只使用 timestamp 作为 'regular' 浮点值参数(我想当任务得到 运行 时)。

我的完整答案是

下面是我想出的解决方案 here it is in Ellie:

module Main exposing (..)

import Html exposing (..)
import Html.Events exposing (..)
import Http
import Json.Decode as JD
import Json.Encode as JE
import Task
import Time


type alias Model =
    { url : String
    }


type Msg
    = PostTimeToServer
    | PostDone (Result Http.Error String)


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        PostTimeToServer ->
            ( model, postTimeToServer model.url )

        PostDone _ ->
            ( model, Cmd.none )


view : Model -> Html Msg
view model =
    div []
        [ div []
            [ button [ onClick PostTimeToServer ] [ Html.text "POST the current time." ]
            ]
        ]


postTimeToServer : String -> Cmd Msg
postTimeToServer url =
    let
        getTime =
            Time.now

        postTime t =
            JD.string
                |> Http.post url (JE.float t |> Http.jsonBody)
                |> Http.toTask

        request =
            getTime                                            <<-- Here is
                |> Task.andThen postTime                       <<-- the key bit.
    in
        Task.attempt PostDone request


main =
    Html.program
        { init = ( Model "url_here", Cmd.none )
        , update = update
        , view = view
        , subscriptions = always Sub.none
        }

榆木 0.19

下面我设置初始时间为unix时间开始Time.millisToPosix 0,但你可以将它设置为Nothing,然后再设置为Just time,或者用Flag传递。

module Main exposing (main)

import Browser
import Html exposing (Html)
import Task
import Time exposing (Posix)


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



-- MODEL


type alias Model =
    { zone : Time.Zone
    , now : Posix
    }


init : ( Model, Cmd Msg )
init =
    ( Model Time.utc (Time.millisToPosix 0), Task.perform Zone Time.here )



-- UPDATE


type Msg
    = Zone Time.Zone
    | Now Posix


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Zone zone ->
            ( { model | zone = zone }, Task.perform Now Time.now )

        Now now ->
            ( { model | now = now }, Cmd.none )



-- VIEW


formatTime zone posix =
    (String.padLeft 2 '0' <| String.fromInt <| Time.toHour zone posix)
        ++ ":"
        ++ (String.padLeft 2 '0' <| String.fromInt <| Time.toMinute zone posix)
        ++ ":"
        ++ (String.padLeft 2 '0' <| String.fromInt <| Time.toSecond zone posix)


view : Model -> Html Msg
view model =
    Html.div []
        [ Html.text <| formatTime model.zone model.now
        ]