Time


Clone the code or follow along in the online editor.


We are going to make a simple clock.

So far we have focused on commands. With the randomness example, we asked for a random value. With the HTTP example, we asked for info from a server. That pattern does not really work for a clock. In this case, we want to sit around and hear about clock ticks whenever they happen. This is where subscriptions come in.

The code is not too crazy here, so I am going to include it in full. After you read through, we will come back to normal words that explain it in more depth.

  1. import Html exposing (Html)
  2. import Svg exposing (..)
  3. import Svg.Attributes exposing (..)
  4. import Time exposing (Time, second)
  5. main =
  6. Html.program
  7. { init = init
  8. , view = view
  9. , update = update
  10. , subscriptions = subscriptions
  11. }
  12. -- MODEL
  13. type alias Model = Time
  14. init : (Model, Cmd Msg)
  15. init =
  16. (0, Cmd.none)
  17. -- UPDATE
  18. type Msg
  19. = Tick Time
  20. update : Msg -> Model -> (Model, Cmd Msg)
  21. update msg model =
  22. case msg of
  23. Tick newTime ->
  24. (newTime, Cmd.none)
  25. -- SUBSCRIPTIONS
  26. subscriptions : Model -> Sub Msg
  27. subscriptions model =
  28. Time.every second Tick
  29. -- VIEW
  30. view : Model -> Html Msg
  31. view model =
  32. let
  33. angle =
  34. turns (Time.inMinutes model)
  35. handX =
  36. toString (50 + 40 * cos angle)
  37. handY =
  38. toString (50 + 40 * sin angle)
  39. in
  40. svg [ viewBox "0 0 100 100", width "300px" ]
  41. [ circle [ cx "50", cy "50", r "45", fill "#0B79CE" ] []
  42. , line [ x1 "50", y1 "50", x2 handX, y2 handY, stroke "#023963" ] []
  43. ]

There is nothing new in the MODEL or UPDATE sections. Same old stuff. The view function is kind of interesting. Instead of using HTML, we use the Svg library to draw some shapes. It works just like HTML though. You provide a list of attributes and a list of children for every node.

The important thing comes in SUBSCRIPTIONS section. The subscriptions function takes in the model, and instead of returning Sub.none like in the examples we have seen so far, it gives back a real life subscription! In this case Time.every:

  1. Time.every : Time -> (Time -> msg) -> Sub msg

The first argument is a time interval. We chose to get ticks every second. The second argument is a function that turns the current time into a message for the update function. We are tagging times with Tick so the time 1458863979862 would become Tick 1458863979862.

That is all there is to setting up a subscription! These messages will be fed to your update function whenever they become available.

Exercises:

  • Add a button to pause the clock, turning the Time subscription off.
  • Make the clock look nicer. Add an hour and minute hand. Etc.