向后移植 Sigils 并使其与变量一起使用

Backporting Sigils and make it work with variables

所以我刚开始使用 Elixir,看到当前的 master 添加了对 ~U[2015-01-13 13:00:07Z] sigil 到 create/parse 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 被解释为原样,而不是之前的匹配项。

有什么方法可以让它发挥作用吗?我需要 quote/unquote 什么吗?除了直接使用 DateTime.from_iso8601/1

sigil 分隔符之间的所有内容都作为字符串发送。所以 timestamp 变量作为字符串 "timestamp" 发送到 sigil_U。有一些印记允许插值,按照惯例是小写的。例如 ~r versus ~R:

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

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

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

但在这种情况下,没有定义 sigil_U 的小写版本,因此您无法插入 timestamp