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