56 lines
1.3 KiB
Elixir
56 lines
1.3 KiB
Elixir
defmodule RDF.Date do
|
|
@moduledoc """
|
|
`RDF.Datatype` for XSD date.
|
|
"""
|
|
|
|
use RDF.Datatype, id: RDF.Datatype.NS.XSD.date
|
|
|
|
@grammar ~r/\A(-?\d{4}-\d{2}-\d{2})((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z/
|
|
|
|
|
|
def convert(%Date{} = value, %{tz: "+00:00"} = opts) do
|
|
{convert(value, Map.delete(opts, :tz)), "Z"}
|
|
end
|
|
|
|
def convert(%Date{} = value, %{tz: tz} = opts) do
|
|
{convert(value, Map.delete(opts, :tz)), tz}
|
|
end
|
|
|
|
# Special case for date and dateTime, for which 0 is not a valid year
|
|
def convert(%Date{year: 0} = value, opts), do: super(value, opts)
|
|
def convert(%Date{} = value, _), do: value
|
|
|
|
def convert(value, opts) when is_binary(value) do
|
|
case Regex.run(@grammar, value) do
|
|
[_, date] ->
|
|
date
|
|
|> do_convert
|
|
|> convert(opts)
|
|
[_, date, zone] ->
|
|
date
|
|
|> do_convert
|
|
|> convert(Map.put(opts, :tz, zone))
|
|
_ ->
|
|
super(value, opts)
|
|
end
|
|
end
|
|
|
|
def convert(value, opts), do: super(value, opts)
|
|
|
|
defp do_convert(value) do
|
|
case Date.from_iso8601(value) do
|
|
{:ok, date} -> date
|
|
_ -> nil
|
|
end
|
|
end
|
|
|
|
|
|
def canonical_lexical(%Date{} = value) do
|
|
Date.to_iso8601(value)
|
|
end
|
|
|
|
def canonical_lexical({%Date{} = value, zone}) do
|
|
canonical_lexical(value) <> zone
|
|
end
|
|
|
|
end
|