91
votes

This seems like a really dumb question but how does one get and display the current date or time in Elixir? I tried going through the docs but couldn't find anything. Do I need to use an Erlang function?

11

11 Answers

69
votes

You can use DateTime.utc_now/0 to get UTC DateTime.

60
votes

To answer your question more specifically (though I really appreciate Onorio's recommendation to use Timex!), you can get the current date and time from the Erlang standard lib using :calendar.universal_time() or :calendar.local_time(). There are a number of useful functions for working with Erlang's datetime type in the calendar module, but they are somewhat limited, and don't provide you with anything for parsing or formatting dates, which is where Timex comes in.

37
votes

From Erlang 19.1:

:os.system_time(:millisecond)

From Erlang 18:

:os.system_time(:milli_seconds)

Gives the current UNIX timestamp UTC.

Thanks @HenrikN for linking the blog post http://michal.muskala.eu/2015/07/30/unix-timestamps-in-elixir.html

19
votes

NaiveDateTime

If you don't care about the timezone and just want pure Date and Time, use NaiveDateTime:

NaiveDateTime.utc_now
# => ~N[2017-11-30 20:49:54.660724]

DateTime

If you want Timezone details as well, use DateTime, which will also return things like timezone name, UTC offset, STD offset, and timezone abbreviation:

DateTime.utc_now
# => %DateTime{calendar: Calendar.ISO, day: 30, hour: 20, microsecond: {667345, 6}, minute: 51, month: 11, second: 58, std_offset: 0, time_zone: "Etc/UTC", utc_offset: 0, year: 2017, zone_abbr: "UTC"}

You can then also call to_date/1 and to_time/1 from these modules to get the specific date and time values from the datetime structs.

12
votes

I think your best bet is to use Paul Schoenfelder's (aka BitWalker) timex library for Elixir. The lib is here: https://github.com/bitwalker/timex and you can get the package from hex.pm https://hex.pm/packages/timex. Paul kindly provided a good explanation of how to use the library on the readme page of that github repo.

You could make calls to the native Erlang libs but I think Paul's lib is superior when one is dealing with Elixir.

12
votes

It depends what format you want it in.

You can use any function in the Erlang standard library from Elixir. Traditionally, you would get the time with the now/0 function:

iex(1)> :erlang.now
{1487, 549978, 29683}

That represents time_t 1,487,549,978.29683, which is 19 minutes, 38.29683 seconds after midnight UTC on Monday, Feb 20, 2017.

However, since Erlang/OTP 18, that function is deprecated; one of the reasons is that Erlang guarantees that the return value will increase every call. If calling it in a tight loop on a machine fast enough to call it more than once per microsecond, the returned timestamp will get ahead of real time.

The replacement is an API with more precision and control. The primary interface to this new API is the os:system_time/0 function, which returns epoch time in a system-defined unit:

iex(2)> :os.system_time
1487549978296838000

You can request a specific unit with system_time/1, though:

iex(3)> :os.system_time(:millisecond)
1487549978296

Since Elixir 1.2, those functions have also been available in the native System module:

iex(4)> System.system_time(:second)
1487549978

For a more friendly but still Elixir-native interface, use the calendar module, which will give you tuples:

iex(5)> :calendar.universal_time
{{2017, 2, 20}, {0, 19, 38}}

Since 1.3, Elixir has also had its own suite of modules for manipulating dates and times: Date and DateTime. You can use its functions to get the current date or time like so:

iex(6)> Date.utc_today
~D[2017-02-20]
iex(7)> DateTime.utc_now
#DateTime<2017-02-20 00:19:38.29683Z>
9
votes

To get the number of milliseconds (Unix Timestamp):

DateTime.utc_now() |> DateTime.to_unix(:millisecond)
8
votes

You can also use :os.timestamp\0, which returns {megaseconds, seconds, microseconds} from UTC. :os.timestamp |> :calendar.now_to_datetime will give you now in erlang standard {{YYYY, MM, DD}, {HH, MM, SS}} format.

6
votes

If you need to deal with Daylight Saving Time or time zones I made a library for that: Calendar.

To get the current time you would use for instance Calendar.DateTime.now("America/Los_Angeles") for the current time in Los Angeles or Calendar.DateTime.now_utc for the current time in UTC.

2
votes

To get unix timestamp

DateTime.to_unix(DateTime.utc_now)
0
votes

Well, Timex to the rescue usually, however some of tricks below might be of help:

{erl_date, erl_time} = :calendar.local_time()
# {{2020, 11, 19}, {0, 6, 36}}

{:ok, time} = Time.from_erl(erl_time)
# {:ok, ~T[00:06:36]}

{:ok, date} = Date.from_erl(erl_date)
# {:ok, ~D[2020-11-19]}

Calendar.strftime(time, "%c", preferred_datetime: "%H:%M:%S")
# "00:06:36"


Calendar.strftime(date, "%c", preferred_datetime: "%m-%d-%Y")
# "11-19-2020"