How to convert Ecto.DateTime to UNIX timestamps?

Hello, I want to convert an inserted_at Ecto.DateTime to a UNIX timestamp.

In Elixir we have to_unix/2 which does the job, but first I’d need to convert the Ecto.DateTime to an Elixir DateTime.

What’s the most straightforward way to do this?

Thanks!

4 Likes

You have to convert the Ecto.DateTime struct to the erlang tuple (via Ecto.DateTime.to_erl/1) and then use :calendar.datetime_to_gregorian_seconds to get the number of gregorian seconds (since day 0) and subtract the unix time in gregorian seconds (62167219200). In one (in)glorious pipeline:

datetime
|> Ecto.DateTime.to_erl
|> :calendar.datetime_to_gregorian_seconds
|> Kernel.-(62167219200)

And now you know exactly why we decided to add Calendar types in Elixir v1.3. :sweat_smile: I hope to soon get back to Ecto and migrate it to use the new Calendar types.

10 Likes

Phew! Thanks! :slight_smile:

There is also a nice blog post http://michal.muskala.eu/2015/07/30/unix-timestamps-in-elixir.html by @michalmuskala

2 Likes

Hey there!

I had this Ecto.DateTime to UNIX timestamp working fine in my app but since I’ve moved to Elixir 1.5 and Phoenix 1.3, this part is no longer working. I must be missing something… See this example, here “w” is loaded with Ecto 2.1.6 and has the typical timestamp.

iex(11)> w.inserted_at
~N[2017-10-18 22:39:26.000000]
iex(12)> w.inserted_at |> Ecto.DateTime.to_erl()
** (FunctionClauseError) no function clause matching in Ecto.DateTime.to_erl/1
(ecto) lib/ecto/date_time.ex:608: Ecto.DateTime.to_erl(~N[2017-10-18 22:39:26.000000])

You got a NaiveDateTime, not an Ecto.DateTime.

You need to use NaiveDateTime.to_erl/1 instead.

3 Likes

That was it! Thanks!