Elm Line Charts Part I: Times and Timezones
webbureaucrat
Posted on September 1, 2020
Elm has a very fine third-party line chart library which I've enjoyed using in my passion project, Chicago Test Out. It's well-documented as a library, but if I haven't used it in a while, I find myself struggling to get started with it. I end up starting at the middle or near the end and then clumsily working backwards from where I want to end up. For this reason,I'm working on writing a step-by-step guide for working with terezka/line-charts
based on my own preferences and assuming a high-degree of customization apart from the defaults, using Chicago Test Out as a model.
One of my preferences is that a line chart almost always be used with time on the x-axis, and you can't use a time without knowing the time zone, so we'll start there.
Step 1: Add a Time.Zone
field to your model.
Time zones have to be fetched asynchronously, which means
- Open the file that has your model record in it and, if you have not already,
import Time
. - Add a field of type
Time.Zone
to yourModel
type record. - In your model initialization, initialize your time zone field to Time.utc.
- Compile.
If you haven't already used elm/time
somewhere, the elm compiler may object and insist that you install the dependency, which it will walk you through Assuming you don't have a lot of different functions that initialize a new model, this should bring your code to a compiling state. I am including the full source for src/Models.elm from Chicago Test out below for reference.
module Models exposing (..)
import Hospitalization exposing (Hospitalization)
import TestDay exposing (TestDay)
import Time
type alias Model =
{ days : List TestDay
, hospitalizations : List Hospitalization
, mode : Mode
, zone: Time.Zone
}
type Mode = Test | HospitalizationMode
init : Model
init =
{ days = []
, hospitalizations = []
, mode = Test
, zone = Time.utc
}
Step 2: Add a time zone update message
- Open the file containing your Elm messages. (Mine is in src/Msg.elm.)
- If you haven't already,
import Time
into that module. - Add an
UpdateZone
type that takes aTime.Zone
parameter, like so:
module Msg exposing (..)
import Hospitalization exposing (Hospitalization)
import Httpimport Json.Encode
import Models exposing (Mode(..))
import RawTestDay exposing (RawTestDay)
import Timetype
Msg = GotRawTestDays (Result Http.Error (List RawTestDay))
| SetMode Mode
| UpdateHospitalizationDays Json.Encode.Value
| UpdateZone Time.Zone
- Implement your new message in your
update
method of your elm application,likely located in src/Main.elm. (You may need toimport Time
here as well.) - Compile.
Your code should be once again in a compiling state.
Get the Timezone from a Task
Now, just hook a Task to getTime.here
into your new message, and you should be up and running with time zones.
This example shows how to do it from init
, but in Chicago Test Out, I want to fetch the time zone after I've run a fetch, so I'm going to hook in from the end of my fetch event.This is what I mean:
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of GotRawTestDays result ->
case result of Ok response ->
TestDay.fromRaws response |> \days ->
({model | days = days}
, Task.perform UpdateZone Time.here
)
Err e -> case e of
.
.
.
That's a lot to look at, but as you can see I'm calling Task.perform
if the response from GotRawTestDays
is Ok
. If the Task is success full, the current time zone, Time.here
will be passed to the message handler ofUpdateZone
.
A word on modelling times in Elm
As a reminder, Elm rejects ISO 8601 as a standard for dates. If you want dates along the x-axis of your chart, you need to have those dates passed as a posix number. For line charts, this should be a Float
type. The steps to get your data will vary, so I won't enumerate them here, but keep that in mind as you work on fetching your line chart dataset: You need a Float
for a date.
In Conclusion
This pretty well covers our prerequisites for working with line charts. In the next post, I'll start to scaffold a real chart.
Posted on September 1, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.