Backporting Sigils и заставить его работать с переменными - PullRequest
0 голосов
/ 06 марта 2019

Так что я только начинаю в Elixir и вижу, что текущий master добавляет поддержку ~U[2015-01-13 13:00:07Z] сигил для создания / анализа даты UTC.

Код следует:

defmodule MySigils do
  defmacro sigil_U(datetime_string, modifiers)

  defmacro sigil_U({:<<>>, _, [string]}, []) do
    Macro.escape(datetime_from_utc_iso8601!(string))
  end

  defp datetime_from_utc_iso8601!(string) do
    case DateTime.from_iso8601(string) do
      {:ok, utc_datetime, 0} ->
        utc_datetime

      {:ok, _datetime, _offset} ->
        raise ArgumentError,
              "cannot parse #{inspect(string)} as UTC datetime, reason: :non_utc_offset"

      {:error, reason} ->
        raise ArgumentError,
              "cannot parse #{inspect(string)} as UTC datetime, reason: #{inspect(reason)}"
    end
  end
end

В моем коде я пытаюсь использовать это с переменной timestamp

timestamp = Map.get(item, "timestamp")
~U[timestamp]
** (ArgumentError) cannot parse "timestamp" as UTC datetime, reason: :invalid_format

но timestamp интерпретируется как есть, а не предыдущее совпадение.

Есть ли способ заставить его работать? Нужно ли что-то цитировать? Помимо непосредственного использования DateTime.from_iso8601/1.

1 Ответ

1 голос
/ 06 марта 2019

Все между символами-разделителями отправляется в виде строки. Поэтому переменная timestamp отправляется на sigil_U в виде строки "timestamp". Существуют некоторые символы, которые допускают интерполяцию, которые условно прописаны в нижнем регистре. Например, ~r против ~R:

iex(1)> x = "foo"
"foo"

iex(2)> ~R/#{x}/
~r/\#{x}/

iex(3)> ~r/#{x}/
~r/foo/

Но в этом случае не определена строчная версия sigil_U, поэтому вы не можете интерполировать timestamp.

...