Elixir Date Comparisons

When comparing Dates (or DateTimes) it’s easy to fall into the trap of using standard comparison functions (==/2, >/2, </2, etc). You’ll get not warnings / compile errors doing this, but you’ll eventually stumble across dates where the returned value is the opposite of what you are expecting.

first_date = Date.from_iso8601!("2021-06-24")
~D[2021-06-24]
iex(2)> second_date = Date.from_iso8601!("2021-06-25")
~D[2021-06-25]
iex(3)> first_date < second_date
true

Looking good right? Ok, let’s try some different dates

first_date = Date.from_iso8601!("2021-06-24")
~D[2021-06-24]
iex(2)> second_date = Date.from_iso8601!("2021-07-23")
~D[2021-07-23]
iex(3)> first_date < second_date
false ### huh???

So what’s going on here? Well, it’s because Dates (or DateTimes) in Elixir are Structs. The properties of the struct are not ordered, so the comparison does not actually understand the structure of Date and how to compare properly. In this case the day values are being compared before the month values, so we end up with a false assertion

How should we compare dates then?

There is a handy compare/2 function for both Date and DateTime which returns either :lt, :eq or :gt, so we can check for that value.

Alternativley you could use the diff/2 function and check if the output is 0, less than 0 or greater than 0

John Polling

Developer, tinkerer, occasionally useful

Tags
Elixir