简体   繁体   中英

Backporting Sigils and make it work with variables

So I'm just starting out in Elixir and saw that the current master adds support for a ~U[2015-01-13 13:00:07Z] sigil to create/parse UTC date.

Code follows:

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

In my code I'm trying to use this with a variable timestamp

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

but timestamp is being interpreted as is, not the previous match.

Is there a way I can make it work? Do I need to quote/unquote something? Beside using DateTime.from_iso8601/1 directly.

Everything between sigil delimiters is sent as a string. So timestamp variable is sent to sigil_U as the string "timestamp" . There are some sigils that allow interpolation which are by convention in lowercase. For example ~r versus ~R :

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

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

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

But in this case no lowercase version of sigil_U is defined so you can't interpolate timestamp .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM