rdf-ex/lib/rdf/datatypes/date_time.ex
2018-08-10 23:51:04 +02:00

73 lines
2 KiB
Elixir

defmodule RDF.DateTime do
@moduledoc """
`RDF.Datatype` for XSD dateTime.
"""
use RDF.Datatype, id: RDF.Datatype.NS.XSD.dateTime
# Special case for date and dateTime, for which 0 is not a valid year
def convert(%DateTime{year: 0} = value, opts), do: super(value, opts)
def convert(%DateTime{} = value, _), do: value
# Special case for date and dateTime, for which 0 is not a valid year
def convert(%NaiveDateTime{year: 0} = value, opts), do: super(value, opts)
def convert(%NaiveDateTime{} = value, _), do: value
def convert(value, opts) when is_binary(value) do
case DateTime.from_iso8601(value) do
{:ok, date_time, _} -> convert(date_time, opts)
{:error, :missing_offset} ->
case NaiveDateTime.from_iso8601(value) do
{:ok, date_time} -> convert(date_time, opts)
_ -> super(value, opts)
end
{:error, :invalid_time} ->
if String.contains?(value, "T24:00:00") do
with [day, tz] <- String.split(value, "T24:00:00", parts: 2),
{:ok, day} <- Date.from_iso8601(day)
do
"#{day |> Date.add(1) |> Date.to_string()}T00:00:00#{tz}"
|> convert(opts)
else
_ -> super(value, opts)
end
else
super(value, opts)
end
_ ->
super(value, opts)
end
end
def convert(value, opts), do: super(value, opts)
def canonical_lexical(%DateTime{} = value) do
DateTime.to_iso8601(value)
end
def canonical_lexical(%NaiveDateTime{} = value) do
NaiveDateTime.to_iso8601(value)
end
def tz(datetime_literal) do
if valid?(datetime_literal) do
lexical = lexical(datetime_literal)
case Regex.run(~r/([+-])(\d\d:\d\d)/, lexical) do
[_, sign, zone] ->
sign <> zone
_ ->
if String.ends_with?(lexical, "Z") do
"Z"
else
""
end
end
end
end
end