Elixir's standard library offers 4 different modules for working with dates and time, each with its own struct.
The Date
module. A Date
struct can be created with the ~D
sigil.
~D[2021-01-01]
The Time
module. A Time
struct can be created with the ~T
sigil.
~T[12:00:00]
The NaiveDateTime
module for datetimes without a timezone. A NaiveDateTime
struct can be created with the ~N
sigil.
~N[2021-01-01 12:00:00]
The DateTime
module for datetimes with a timezone. Using this module for timezones other than UTC requires an external dependency, a timezone database. A DateTime
struct can be represented with the ~U
sigil, but should be created using DateTime
functions instead.
DateTime.new!(~D[2021-01-01], ~T[12:00:00], "Etc/UTC")
# => ~U[2021-01-01 12:00:00Z]
To compare dates or times to one another, look for a compare
or diff
function in the corresponding module. Comparison operators such as ==
, >
, and <
seem to work, but they don't do a correct semantic comparison for those structs.
Date.compare(~D[2020-11-30], ~D[2020-12-01])
# => :lt
Time.diff(~T[13:45:00], ~T[13:46:30])
# => -90
Dates, time, and datetimes can be shifted forwards and backwards in time using the add/2
function from the corresponding module.
# add 4 days
Date.add(~D[2021-01-01], 4)
# => ~D[2021-01-05]
# subtract 1 second
Time.add(~T[12:00:00], -1)
# => ~T[11:59:59.000000]
# add 4 days and 30 seconds
NaiveDateTime.add(~N[2021-01-01 12:00:00], 4 * 24 * 60 * 60 + 30)
# => ~N[2021-01-05 12:00:30]
A NaiveDateTime
struct can be deconstructed into a Date
struct and a Time
struct using NaiveDateTime.to_date/1
and NaiveDateTime.to_time/1
. The opposite can be achieved with NaiveDateTime.new!/2
.
NaiveDateTime.to_date(~N[2021-01-01 12:00:00])
# => ~D[2021-01-01]
NaiveDateTime.to_time(~N[2021-01-01 12:00:00])
# => ~T[12:00:00]
NaiveDateTime.new!(~D[2021-01-01], ~T[12:00:00])
# => ~N[2021-01-01 12:00:00]