Menu

Unix Timestamps in Elixir

Lately, there were several people asking on IRC how to deal with unix
timestamps in
Elixir, so I decided to write a little bit more about this.

UPDATE: Since this blog post was created a lot changed and getting timestamps
and managing calendar types (dates, datetimes, times) got a lot easier in
Elixir in general. Consider checking out
the updated version of this post

What should I use?

Elixir’s standard library doesn’t have any modules dealing with times, dates or
any of that, but we can always reach out to Erlang. In Erlang there are
basically three modules dealing with dates and times:

The os, and erlang modules, where,
we can find functions that can help us with what I’ll call “machine time”.
As a base format they use the :erlang.timestamp type
(defined as three element tuples {megaseconds, seconds, microseconds}), or simple integers.
They operate assuming 01.01.1970 as the beginning of the time.

The calendar module, that deals with human-readable dates and times.
It uses date tuples in format of {year, month, day} and time tuples
in format of {hour, minute, second} or even datetime tuples combining the two:
{date_tuple, time_tuple}. It assumes the
beginning of the time was 01.01.0000 as defined by the ISO 8601 standard (year
0 in fact being 1 BC).

If you need anything more than simple conversions, or need to deal with time
zones, I would recommend using a proper library for that, like the excellent
Timex.
But when all you need is a simple conversion here and there, pulling in an
entire library for one or two functions may be excessive.

Converting timestamps

That’s probably the most frequent use case - you need to convert between the
datetime tuples and timestamps. You can achieve that using the calendar
module.

If you’re looking to convert those between Ecto types in Phoenix, you can use
Ecto.DateTime.to_erl/1 and Ecto.DateTime.from_erl/1 as additional steps in
the pipeline.

Generating timestamps

If you’re on Erlang 18 the easiest way is to use newly introduced function,
where you can specify the unit you want to receive:

deftimestampdo:os.system_time(:seconds)end

There are also other formats allowed: :milli_seconds, :micro_seconds,
:nano_seconds, and :native (as used internally by the Erlang runtime system).
You can also use a parts_per_second integer (:seconds is just alias to 1,
:milli_seconds is just an alias to 1000, etc.).

Further reading

If you want to learn more about how time works in the Erlang runtime system, I
can’t recommend enough
learn you some Erlang’s chapter on time.
You should also look at the
Erlang’s documentation
explaining different times (yes there are more then one!) the Erlang runtime
system deals with.