Elm Line Charts Part I: Times and Timezones
Tags: elm, datavisualization, dataviz
Published: 2020-09-01 17:14:52

---
title: Elm Line Charts Part I: Times and Timezones
published: true
date: 2020-07-26 00:00:00 UTC
tags: ["elm", "datavisualization", "dataviz"]
canonical_url: https://webbureaucrat.gitlab.io/posts/elm-line-charts-part-i-times-and-timezones/
---

Elm has a [very fine third-party line chart library](https://package.elm-lang.org/packages/terezka/line-charts/2.0.1/LineChart) which I've enjoyed using in my passion project, [Chicago Test Out](https://chicagotestout.netlify.app/). 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](https://chicagotestout.netlify.app/) 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

1. Open the file that has your model record in it and, if you have not already, `import Time`.
2. Add a field of type `Time.Zone` to your `Model` type record.
3. In your model initialization, initialize your time zone field to Time.utc.
4. 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.

```elm
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

1. Open the file containing your Elm messages. (Mine is in _src/Msg.elm_.)
2. If you haven't already, `import Time` into that module.
3. Add an `UpdateZone` type that takes a `Time.Zone` parameter, like so:

```elm
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
```

1. Implement your new message in your `update` method of your elm application,likely located in _src/Main.elm_. (You may need to `import Time` here as well.)
2. Compile.

Your code should be once again in a compiling state.

### Get the Timezone from a Task

Now, just hook a [Task](https://package.elm-lang.org/packages/elm/core/latest/Task) to get`Time.here` into your new message, and you should be up and running with time zones.

[This example](https://guide.elm-lang.org/effects/time.html) 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:

```elm
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 of`UpdateZone`.

### 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](https://webbureaucrat.gitlab.io/posts/elm-line-charts-part-ii-imports-and-axes/), I'll start to scaffold a real chart.