【问题标题】:How do I get the current time in Elm?如何获取 Elm 的当前时间?
【发布时间】:2026-01-07 01:00:01
【问题描述】:

我正在运行 elm-repl 来玩弄该语言。

我想看看现在是几点。我该怎么做?当前的库似乎不可能。这是为什么呢?


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

这是围绕 elm 0.15 提出的问题 - elm 0.17 和 0.18 中的情况有所不同:请参阅 How do I get the current time in Elm 0.17/0.18?

【问题讨论】:

标签: time elm


【解决方案1】:

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

【讨论】:

  • 为了大家的利益,我在这里*.com/q/38021777/131227再次问了这个问题(0.17)。我的看法是,很容易得到你展示的时间。但是获取任意消息发生的时间要复杂得多(不可能)。许多应用程序都有这种类型的簿记要求,其中维护“created_at”或“updated_at”值。
  • { type = "leaf", home = "Task", value = Perform <task> } : Platform.Cmd.Cmd Repl.Msg 你如何得到实际的Time
  • 看看 Ellie 链接到
  • 仅供参考,在 Elm 0.19 中 Time.now 已移动到单独的包中,elm/time
  • 谢谢,我不得不说,虽然这并不容易,更不用说变得更容易了。
【解决方案2】:

您可以使用the Time package 和/或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 中获取当前时间”。相反,这是在回答这个问题,“我怎样才能在时间频率的基础上执行任务,并将时间传递给它”。这种方式能否适应“调用函数返回当前系统时间”的情况?
  • @TomKludy 我认为您的要求是不可能的,因为该功能必然是不纯的。根据@Apanatshka 的观点,您可以使用Task 并传递一个回调,该回调将接收系统调用后的时间,或者使用TaskMailbox,这会导致值被发回在程序可用后进入您的程序。见Chaining TasksCommunicating with Mailboxes here
  • 我认为这是那些会很快让从业者放弃使用函数式语言的具体事情之一。您正在编写解码器来解析传入的消息,并且基本上您没有优雅的方式将时间戳粘贴到它们上,除非它们已经带有时间戳。感觉有点像智能手机,只有先添加联系人才能给某人打电话……
  • @Gabor - 任何编写单元测试来覆盖执行 getSystemTime() 调用的代码的人都可以证明,在给定相同参数时,很难测试执行不同操作的代码。使用功能方法,单元测试实际上变得快乐!练习者应该喜欢这个。好吧,公平地说,您可以使用依赖注入或猴子补丁,但我们知道这些解决方案不太令人满意。
  • @MartinCapodici 你能解释一下为什么有一种简单的方法可以得到一个随机数而不是当前时间吗? :P 编辑:我收回。只是有关于如何生成随机数的文档。但不是如何获取当前时间。
【解决方案3】:

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

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

【讨论】:

  • 确实是一个不错的方法。我当时正在考虑做一些在模型中使用特殊值的事情。然而,这种方法是在最抽象的层次上工作的,不需要对你的应用程序或模型一无所知。它非常优雅。
【解决方案4】:

榆树 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
        ]

【讨论】:

    【解决方案5】:

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

    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
    

    【讨论】:

    • 我得到了这个工作,这解决了我的问题。谢谢!关键是在我的 elm-package.json 中包含以下内容:"native-modules": true
    【解决方案6】:

    您可以查看pdoherty926's answer,了解如何使用 Elm 中的当前时间进行操作。

    elm-repl 无法与Signals 一起工作,并且时间“随时间而变化”,因此它是一个信号。 据我所知,也没有Task 来获取时间。也不是在 repl 中执行任务的方法,尽管我希望这将成为未来的功能。

    【讨论】:

      【解决方案7】:

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

      1. 编写/使用本机模块创建一个以毫秒为单位返回当前时间的函数(或返回将执行相同操作的任务)。一般不推荐这种方法。我认为#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/) 编写程序,然后将当前时间信号作为输入提供给更新周期,在您选择的每个间隔使用新的当前时间更新模型。然后你所有的其他方法都可以同步地从模型中获取当前时间。

      【讨论】:

      • 扩展想法 #2,我认为这是最好的:type Action = Tick Time | ... 并更新:Tick time -&gt; {model | time = time}
      【解决方案8】:

      Simon H 的答案(针对 0.18)让我开始朝着正确的方向前进,但我确实在弄清楚如何在那个时候真正做某事时遇到了一些麻烦。 (user2167582 在 Simon 的回答中添加了一条评论,提出了同样的问题:你如何“抽出时间?”)。

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

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

      我的完整答案是here

      以下是我想出的解决方案和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
              }
      

      【讨论】:

        最近更新 更多