diff --git a/lib/elixir/lib/kernel.ex b/lib/elixir/lib/kernel.ex index 2311cb5e757..be0387cccea 100644 --- a/lib/elixir/lib/kernel.ex +++ b/lib/elixir/lib/kernel.ex @@ -5635,9 +5635,17 @@ defmodule Kernel do iex> ~D[2015-01-13] ~D[2015-01-13] + `~D` might be also called with empty content, returning the current date in UTC. + It’s a syntactic sugar for `Date.utc_today/0`. """ defmacro sigil_D(date_string, modifiers) + defmacro sigil_D({:<<>>, _, [""]}, []) do + quote do + Date.utc_today() + end + end + defmacro sigil_D({:<<>>, _, [string]}, []) do {{:ok, {year, month, day}}, calendar} = parse_with_calendar!(string, :parse_date, "Date") to_calendar_struct(Date, calendar: calendar, year: year, month: month, day: day) @@ -5675,9 +5683,30 @@ defmodule Kernel do iex> ~T[13:00:07.001] ~T[13:00:07.001] + `~T` might be called with empty content to get to the current UTC time, + with the precision specified by a modifier. + + ## Examples + iex> now_without_milliseconds = ~T[]s + ...> now_without_milliseconds.microsecond + {0, 0} + """ defmacro sigil_T(time_string, modifiers) + defmacro sigil_T({:<<>>, _, [""]}, modifiers) do + truncate_to = + case modifiers do + [?s] -> :second + [?m] -> :millisecond + [] -> :microsecond + end + + quote bind_quoted: [truncate_to: truncate_to] do + Time.utc_now() |> Time.truncate(truncate_to) + end + end + defmacro sigil_T({:<<>>, _, [string]}, []) do {{:ok, {hour, minute, second, microsecond}}, calendar} = parse_with_calendar!(string, :parse_time, "Time") @@ -5780,10 +5809,30 @@ defmodule Kernel do iex> ~U[2015-01-13T13:00:07.001+00:00] ~U[2015-01-13 13:00:07.001Z] + `~U` might be called with empty content to get to the current UTC datetime, + with the precision specified by a modifier. + + ## Examples + iex> now_without_milliseconds = ~U[]s + ...> now_without_milliseconds.microsecond + {0, 0} """ @doc since: "1.9.0" defmacro sigil_U(datetime_string, modifiers) + defmacro sigil_U({:<<>>, _, [""]}, modifiers) do + truncate_to = + case modifiers do + [?s] -> :second + [?m] -> :millisecond + [] -> :microsecond + end + + quote bind_quoted: [truncate_to: truncate_to] do + DateTime.utc_now() |> DateTime.truncate(truncate_to) + end + end + defmacro sigil_U({:<<>>, _, [string]}, []) do {{:ok, {year, month, day, hour, minute, second, microsecond}, offset}, calendar} = parse_with_calendar!(string, :parse_utc_datetime, "UTC DateTime") diff --git a/lib/elixir/test/elixir/calendar/date_test.exs b/lib/elixir/test/elixir/calendar/date_test.exs index 763c11a6a25..af933a3694d 100644 --- a/lib/elixir/test/elixir/calendar/date_test.exs +++ b/lib/elixir/test/elixir/calendar/date_test.exs @@ -13,6 +13,10 @@ defmodule DateTest do assert ~D[20001-01-01 Calendar.Holocene] == %Date{calendar: Calendar.Holocene, year: 20001, month: 1, day: 1} + {now1, now2} = {Date.utc_today(), ~D[]} + # to be safe running at midnight + assert Date.diff(now1, now2) <= 1 + assert_raise ArgumentError, ~s/cannot parse "2000-50-50" as Date for Calendar.ISO, reason: :invalid_date/, fn -> Code.eval_string("~D[2000-50-50]") end diff --git a/lib/elixir/test/elixir/calendar/time_test.exs b/lib/elixir/test/elixir/calendar/time_test.exs index 1285f7df515..bf3e5cc4153 100644 --- a/lib/elixir/test/elixir/calendar/time_test.exs +++ b/lib/elixir/test/elixir/calendar/time_test.exs @@ -13,6 +13,9 @@ defmodule TimeTest do assert ~T[12:34:56 Calendar.Holocene] == %Time{calendar: Calendar.Holocene, hour: 12, minute: 34, second: 56} + {now1, now2} = {Time.utc_now(), ~T[]} + assert Time.diff(now1, now2) <= 2 + assert_raise ArgumentError, ~s/cannot parse "12:34:65" as Time for Calendar.ISO, reason: :invalid_time/, fn -> Code.eval_string("~T[12:34:65]") end diff --git a/lib/elixir/test/elixir/kernel_test.exs b/lib/elixir/test/elixir/kernel_test.exs index f64f910b4a4..694ce01bd76 100644 --- a/lib/elixir/test/elixir/kernel_test.exs +++ b/lib/elixir/test/elixir/kernel_test.exs @@ -1399,6 +1399,9 @@ defmodule KernelTest do zone_abbr: "UTC" } + {now1, now2} = {DateTime.utc_now(), ~U[]} + assert DateTime.diff(now1, now2) <= 2 + assert_raise ArgumentError, ~r"reason: :invalid_format", fn -> Code.eval_string(~s{~U[2015-01-13 13:00]}) end