How to parse DateTime in Elixir?

10,946

Solution 1

To get the current date and or time, you can use one of

Ecto.Date.utc
Ecto.Time.utc
Ecto.DateTime.utc
DateTime.utc_now

As for converting a {DD, MM, YY} tuple into an Ecto.Date, you will not be able to do that with ecto provided functions. However, you can use a {YYYY, MM, DD} tuple to convert into Ecto.Date.

Ecto.Date.from_erl({2016, 12, 4})
#Ecto.Date<2016-12-04>

Date.from_erl({2016, 12, 4})
{:ok, ~D[2016-12-04]}

Ecto.Time.from_erl({13, 55, 10})
#Ecto.Time<12:10:08>

Ecto.Time.from_erl({13, 55, 10})
{:ok, ~T[13:55:10]}

Ecto.DateTime.from_erl({{2016, 12, 4}, {13, 55, 10}})
#Ecto.DateTime<2016-12-04 13:55:10>

Ecto.Date.from_erl({2016, 12, 4}) |> Ecto.DateTime.from_date()
#Ecto.Date<2016-12-04>

You just need to make sure your data is in the proper order these functions expect them to be.

As for parsing these from a string, you are either going to need to bring in another library, or write a parser yourself.

Solution 2

Just adding to the answer given by Justin. Elixir's standard library can parse ISO 8601 dates.

iex> Date.from_iso8601("2015-01-23")
{:ok, ~D[2015-01-23]}

or with the bang-version, that might raise errors:

iex> Date.from_iso8601!("2015-01-23")
~D[2015-01-23]

If you want a full datetime from an ISO 8601 string, you'll have to be satisfied with a NaiveDateTime, since there's no reliable time zone information to go on.

iex> NaiveDateTime.from_iso8601("2015-01-23 23:50:07")
{:ok, ~N[2015-01-23 23:50:07]}

Beware, it will simply throw away time zone offsets.

There is going to be a from_iso8601/1 on DateTime in the future, but it was recently added and has not been released as of Elixir v1.3.4. It will preserve time zone offset, but set the time zone to UTC.

Solution 3

As Martin Svalin and Erik Vullings already commented here, you can now parse strings to DateTime in pure Elixir:

iex(5)> {:ok, date_time, offset} = DateTime.from_iso8601("2018-03-17 21:23:12+0100")
{:ok, #DateTime<2018-03-17 20:23:12Z>, 3600}

As you can see, I set an offset of +1 hour in my string. It was parsed correctly, but a DateTime object doesn't keep timezone information, and when I print it, it displays the correct date and time, but printed by default in UTC.

If you want to keep the original timezone information, that's stored as an offset in seconds in the third element of the tuple (offset in my example above).

Share:
10,946
Kooooro
Author by

Kooooro

Updated on June 20, 2022

Comments

  • Kooooro
    Kooooro almost 2 years

    How can I create (Ecto.)DateTime out of a tuple {DD, MM, YY}, or parse it from a string in Elixir? Should I use DateTime from Erlang for that?

    I've googled but haven't found anything and there's nothing in the documentation about the matter, only about DateTime in general -- how to get the current date and time, for example.

    Note that I don't want to use a third-party library such as Timex.

  • Erik Vullings
    Erik Vullings over 6 years
    This function, from_iso8601/1 has been implemented in Elixir v1.5.1.
  • Ashish Sharma
    Ashish Sharma over 3 years
    How can I print date in string format and not in ~D[some-date] ?
  • Martin Svalin
    Martin Svalin over 3 years
    Elixir 1.11 added a Calendar.strftime/3 function that will cover most datetime related printing needs, but the simplest way is to pass the date to Date.to_string/1. This will return the date formatted according to its calendar, so for a date in Calendar.ISO, that would be yyyy-mm-dd.