Working with Dates and Time in Elm
I remember the first time I started looking into using dates and times within an Elm project that I was working on. It wasn’t the easiest thing. Granted, I’m new to Elm and so it could be my lack of understanding around Tasks and Commands, but I just couldn’t figure it out.
Using a static date or time isn’t bad at all. However, if you want to get the current date or time, you have to be able to perform a side-effect. Given that Elm doesn’t allow you to write side-effects within your functions, it’s not as easy as Date.now(), like in other languages. Let’s dive deeper into how you can use them!
Date
Getting Current Date
When I look at the documentation on elm-lang for Date. I see that they have a handy function for getting the current date, Date.now
.
Maybe it’s because I’m new to Elm, but I don’t really know what to do with that return type Task x Date
.
After scouring the internet to no avail, I fiddled around with Elm until I was able to use this Task x Date
return type.
Before we look at some code, I want to explain commands a little bit. I like to compare using commands within the Elm architecture to calling a web service asynchronously. When you make a request to get data, you don’t get the data back right away. Likewise, when we tell Elm that we’d like to get the current date, we don’t get it back right away. But the Elm architecture is able to call us once the data is there. This is Elm’s way of keeping the code you write pure, even though, in the end, side-effects do happen. If we didn’t have any side-effects, we wouldn’t be able to have a useful program.
Let’s look at some code now.
To start off, let’s think about what program we’re going to make to test this out. There are examples in the Elm Guide around how to work with Time using Subscriptions, but we’re going to focus more on getting the current time, on demand. So our program will have a UI with a button and text. The text will display the date as a string (if it has one) and the button will be there for you to click to request the current date. Once we get the current date, we’ll update our model so that the text will display the date.
Setting up your program
Edit: you can follow along if you start out with the following code (make sure to run elm-make
to get the elm dependencies). The only difference is that you’d need to change Html.beginnerProgram
to Html.program
and the model
method to init
and you should be good to go!
You’ll need to make sure that your main function is using a Html.program (or a similar one that supports commands). To execute a task, you need to send a command to Elm.
Import the appropriate Date and Task modules.
Now we’re ready to come up with our model and then hook up our init, update, and view functions.
Model
To keep it simple, the model is a record with a date that possibly has a value (as seen below). It uses the Maybe union type to allow us to start off the value with Nothing
and then later add a value.
Init
This initializes our model on program load.
Msg
Our msg type will allow us to know what kind of update to perform. This could be triggered from the UI or the Elm architecture.
Update & View
Now for the meat of what we’re trying to accomplish. When our button “Request Date” is pressed, it will send the Msg RequestDate
. Our update
method is able to pick up that message and talk to Elm giving our current model as the next model and a command indicating that we would like to perform a task that will call ReceiveDate
with it’s return value. So since Date.now has a signiture of Task x Date
, we know that when we push that through Task.perform
, it’ll call the update function with msg type of ReceiveDate
with a Date
object. We store this in our date model field and we have our date in memory!
After running this program, this is what we can see in the UI.
Time
Getting current Time
The signature for getting Time is the same as getting a Date. Time.now returns Task x Time
. We’re able to pass through Task.perform
just like above.
The code for the example above can be found in my Github Repository.