【问题标题】:Elm Current Date榆树当前日期
【发布时间】:2016-03-09 11:15:38
【问题描述】:

在 elm 中,我有一个包含 currentDate 的模型,它是一个代表日期的字符串。我用一个信号更新它:

Signal.map (SetCurrentDate << timeToDateString) (Time.every Time.second)

SetCurrentDate是更新模型的动作 (SetCurrentDate date -&gt; { model | currentDate &lt;- date}),timeToDateString 将时间转换为类似“yyyy-mm-dd”的字符串。

但是,这样做有两个问题:

  • model.currentDate 仅在一秒钟后正确设置。因此,在应用程序开始时会有一秒钟的 currentDate 设置不正确。
  • model.currentDate 每秒设置一次,尽管它每天都在变化。

有没有办法解决这个问题?所以 currentDate 是在应用启动时设置的(没有一秒钟的延迟),并且每天只更新一个?

额外发现:

如果我将信号更改为Signal.dropRepeats &lt;| Signal.map (SetCurrentDate &lt;&lt; timeToDateString) (Time.every Time.second)(因此我放弃了重复),则仅在日期更改时才会触发信号,而不是在应用程序启动时触发一次。

编辑:如果有更好的方法来了解 Elm 应用程序中的 currentDate,我很想听听。我的谷歌搜索什么也没提供。

谢谢!

【问题讨论】:

标签: date elm


【解决方案1】:

Apanatshka 的回答 (andothers) 是有道理的,但作为 Elm 的初学者,我很难将解释应用于实际代码。经过一番折腾,这里是呈现自动更新日期所需的最少量代码(使用 Elm v0.16.0):

import Signal
import Html exposing (Html, text)
import Time exposing (Time, every)
import Date exposing (Date, Month, fromTime, year, month, day, hour, minute, second)

-- not used by foldp (https://stackoverflow.com/a/34095298/480608)
startTime = 0

type Action = Update Date

type alias Model = Date

showDate : Date -> String
showDate date = toString (month date) ++ " " ++
  toString (day date) ++ ", " ++
  toString (year date) ++ "  " ++
  toString (hour date) ++ ":" ++
  toString (minute date) ++ ":" ++
  toString (second date)

update : Action -> Model -> Model
update (Update date) _ = date

model : Signal Model
model =
  Signal.foldp update (fromTime startTime) clock

timeToAction : Time -> Action
timeToAction time = Update <| fromTime time

clock : Signal Action
clock =
  Signal.map timeToAction <| every Time.second

main : Signal Html
main =
  Signal.map view model

view : Model -> Html
view model =
  text <| showDate model

这是一个稍微复杂一点的例子,它将时钟合并到其他信号中。不知道这在多大程度上符合 elm 最佳实践,但它确实有效,而且它可以作为一个有用的学习工具,就像它对我所做的那样。

import Signal
import Html exposing (..)
import Html.Events exposing (..)
import Keyboard
import Char
import Time exposing (Time)
import Date exposing (Date, Month, fromTime, year, month, day, hour, minute, second)

startTime = 0

type Action =
  NoOp
  | Increment
  | Decrement
  | Update Time

type alias Model = {
  count: Int,
  time: Time
}

showDate : Date -> String
showDate date = toString (month date) ++ " " ++
  toString (day date) ++ ", " ++
  toString (year date) ++ "  " ++
  toString (hour date) ++ ":" ++
  toString (minute date) ++ ":" ++
  toString (second date)

actions : Signal.Mailbox Action
actions =
  Signal.mailbox NoOp

update : Action -> Model -> Model
update action model =
  case action of
    NoOp -> model
    Increment -> { model | count = model.count + 1 }
    Decrement -> { model | count = model.count - 1 }
    Update time -> { model | time = time }

model : Signal Model
model =
  Signal.foldp update { count = 0, time = startTime } (Signal.mergeMany [
    actions.signal,
    keyPressesToAction,
    clock
  ])

keyPressesToAction : Signal Action
keyPressesToAction =
  let
    keyCodeToAction keyCode =
      case Char.fromCode keyCode of
        '=' -> Increment
        '-' -> Decrement
        _ -> NoOp
  in
    Signal.map keyCodeToAction Keyboard.presses

timeToAction : Time -> Action
timeToAction time = Update time

clock : Signal Action
clock = Signal.map timeToAction (Time.every Time.second)

main : Signal Html
main =
  Signal.map (view actions.address) model

view : Signal.Address Action -> Model -> Html
view address model =
  div [] [
    text <| showDate <| fromTime model.time,
    div []
      [ button [ onClick address Decrement ] [ text "-" ]
      , text <| toString model.count
      , button [ onClick address Increment ] [ text "+" ]
      ]
  ]

【讨论】:

【解决方案2】:

使用信号

您使用的是StartApp 还是您自己的foldp?如果您使用StartApp,最好查找start 函数的代码并将其内联,以便您可以访问foldp

Signal.foldp 不对信号的初始值做任何事情。因此,如果您使用Time.every second 信号,您只能在一秒钟后获得更新,如果您使用日期转换和Signal.dropRepeats,则只能在一天后获得。您可以使用来自第 3 方 signal-extra 库* 的 Signal.Extra.foldp' 来解决此问题。它需要一个函数来从输入的初始值创建foldp 的初始状态。

*完全披露:我是图书馆的作者

使用任务

task-tutorial 库中有一个非常有用的任务,称为getCurrentTime。我认为这可以满足您的需求,而无需每秒更新的信号。与Task.sleep 一起,您可能会得到每天只检查一次或两次时间的东西。

【讨论】:

  • 这似乎工作得很好。非常感谢您非常明确的回答!
  • 我最终也使用了教程中的getCurrentTime,因为它与 Elm StartApp 配合得很好。我真的很想在 Elm 标准库中看到类似的东西。我花了很长时间才弄清楚这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多