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?



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:

|> 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.


Phew! Thanks! :slight_smile:

There is also a nice blog post by @michalmuskala


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.


That was it! Thanks!