Add implementation of RDF.Datatype.cast/1 on all time-related datatypes
This commit is contained in:
parent
65a08c7754
commit
e0635b42ad
7 changed files with 213 additions and 0 deletions
|
@ -5,6 +5,8 @@ defmodule RDF.Date do
|
|||
|
||||
use RDF.Datatype, id: RDF.Datatype.NS.XSD.date
|
||||
|
||||
import RDF.Literal.Guards
|
||||
|
||||
@grammar ~r/\A(-?\d{4}-\d{2}-\d{2})((?:[\+\-]\d{2}:\d{2})|UTC|GMT|Z)?\Z/
|
||||
|
||||
|
||||
|
@ -53,4 +55,35 @@ defmodule RDF.Date do
|
|||
canonical_lexical(value) <> zone
|
||||
end
|
||||
|
||||
|
||||
def cast(%RDF.Literal{datatype: datatype} = literal) do
|
||||
cond do
|
||||
not RDF.Literal.valid?(literal) ->
|
||||
nil
|
||||
|
||||
is_xsd_date(datatype) ->
|
||||
literal
|
||||
|
||||
is_xsd_datetime(datatype) ->
|
||||
case literal.value do
|
||||
%NaiveDateTime{} = datetime ->
|
||||
datetime
|
||||
|> NaiveDateTime.to_date()
|
||||
|> new()
|
||||
|
||||
%DateTime{} = datetime ->
|
||||
datetime
|
||||
|> DateTime.to_date()
|
||||
|> new(%{tz: RDF.DateTime.tz(literal)})
|
||||
end
|
||||
|
||||
is_xsd_string(datatype) ->
|
||||
literal.value
|
||||
|> new()
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -60,6 +60,34 @@ defmodule RDF.DateTime do
|
|||
NaiveDateTime.to_iso8601(value)
|
||||
end
|
||||
|
||||
|
||||
def cast(%RDF.Literal{datatype: datatype} = literal) do
|
||||
cond do
|
||||
not RDF.Literal.valid?(literal) ->
|
||||
nil
|
||||
|
||||
is_xsd_datetime(datatype) ->
|
||||
literal
|
||||
|
||||
is_xsd_date(datatype) ->
|
||||
case literal.value do
|
||||
{value, zone} ->
|
||||
RDF.Date.canonical_lexical(value) <> "T00:00:00" <> zone
|
||||
value ->
|
||||
RDF.Date.canonical_lexical(value) <> "T00:00:00"
|
||||
end
|
||||
|> new()
|
||||
|
||||
is_xsd_string(datatype) ->
|
||||
literal.value
|
||||
|> new()
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def tz(%Literal{value: %NaiveDateTime{}}), do: ""
|
||||
|
||||
def tz(datetime_literal) do
|
||||
|
|
|
@ -109,4 +109,36 @@ defmodule RDF.Time do
|
|||
end
|
||||
end
|
||||
|
||||
def cast(%RDF.Literal{datatype: datatype} = literal) do
|
||||
cond do
|
||||
not RDF.Literal.valid?(literal) ->
|
||||
nil
|
||||
|
||||
is_xsd_time(datatype) ->
|
||||
literal
|
||||
|
||||
is_xsd_datetime(datatype) ->
|
||||
case literal.value do
|
||||
%NaiveDateTime{} = datetime ->
|
||||
datetime
|
||||
|> NaiveDateTime.to_time()
|
||||
|> new()
|
||||
|
||||
%DateTime{} ->
|
||||
[_date, time_with_zone] =
|
||||
literal
|
||||
|> RDF.DateTime.canonical_lexical_with_zone()
|
||||
|> String.split("T", parts: 2)
|
||||
new(time_with_zone)
|
||||
end
|
||||
|
||||
is_xsd_string(datatype) ->
|
||||
literal.value
|
||||
|> new()
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -73,4 +73,42 @@ defmodule RDF.DateTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "cast/1" do
|
||||
test "casting a date returns the input as it is" do
|
||||
assert RDF.date("2010-01-01") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01")
|
||||
end
|
||||
|
||||
test "casting a string" do
|
||||
assert RDF.string("2010-01-01") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01")
|
||||
assert RDF.string("2010-01-01Z") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01Z")
|
||||
assert RDF.string("2010-01-01+01:00") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01+01:00")
|
||||
end
|
||||
|
||||
test "casting a datetime" do
|
||||
assert RDF.date_time("2010-01-01T01:00:00") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01")
|
||||
assert RDF.date_time("2010-01-01T00:00:00Z") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01Z")
|
||||
assert RDF.date_time("2010-01-01T00:00:00+00:00") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01Z")
|
||||
assert RDF.date_time("2010-01-01T23:00:00+01:00") |> RDF.Date.cast() ==
|
||||
RDF.date("2010-01-01+01:00")
|
||||
end
|
||||
|
||||
test "with invalid literals" do
|
||||
assert RDF.date("02010-01-00") |> RDF.Date.cast() == nil
|
||||
assert RDF.date_time("02010-01-01T00:00:00") |> RDF.Date.cast() == nil
|
||||
end
|
||||
|
||||
test "with literals of unsupported datatypes" do
|
||||
assert RDF.false |> RDF.Date.cast() == nil
|
||||
assert RDF.integer(1) |> RDF.Date.cast() == nil
|
||||
assert RDF.decimal(3.14) |> RDF.Date.cast() == nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -123,6 +123,44 @@ defmodule RDF.DateTimeTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "cast/1" do
|
||||
test "casting a datetime returns the input as it is" do
|
||||
assert RDF.date_time("2010-01-01T12:34:56") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T12:34:56")
|
||||
end
|
||||
|
||||
test "casting a string" do
|
||||
assert RDF.string("2010-01-01T12:34:56") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T12:34:56")
|
||||
assert RDF.string("2010-01-01T12:34:56Z") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T12:34:56Z")
|
||||
assert RDF.string("2010-01-01T12:34:56+01:00") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T12:34:56+01:00")
|
||||
end
|
||||
|
||||
test "casting a date" do
|
||||
assert RDF.date("2010-01-01") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T00:00:00")
|
||||
assert RDF.date("2010-01-01Z") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T00:00:00Z")
|
||||
assert RDF.date("2010-01-01+00:00") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T00:00:00Z")
|
||||
assert RDF.date("2010-01-01+01:00") |> RDF.DateTime.cast() ==
|
||||
RDF.date_time("2010-01-01T00:00:00+01:00")
|
||||
end
|
||||
|
||||
test "with invalid literals" do
|
||||
assert RDF.date_time("02010-01-01T00:00:00") |> RDF.DateTime.cast() == nil
|
||||
end
|
||||
|
||||
test "with literals of unsupported datatypes" do
|
||||
assert RDF.false |> RDF.DateTime.cast() == nil
|
||||
assert RDF.integer(1) |> RDF.DateTime.cast() == nil
|
||||
assert RDF.decimal(3.14) |> RDF.DateTime.cast() == nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test "canonical_lexical_with_zone/1" do
|
||||
assert RDF.date_time(~N[2010-01-01T12:34:56]) |> DateTime.canonical_lexical_with_zone() == "2010-01-01T12:34:56"
|
||||
assert RDF.date_time("2010-01-01T12:34:56") |> DateTime.canonical_lexical_with_zone() == "2010-01-01T12:34:56"
|
||||
|
|
|
@ -116,6 +116,12 @@ defmodule RDF.StringTest do
|
|||
test "casting an IRI" do
|
||||
assert RDF.iri("http://example.com") |> RDF.String.cast() == RDF.string("http://example.com")
|
||||
end
|
||||
|
||||
test "with invalid literals" do
|
||||
assert RDF.integer(3.14) |> RDF.Integer.cast() == nil
|
||||
assert RDF.decimal("NAN") |> RDF.Integer.cast() == nil
|
||||
assert RDF.double(true) |> RDF.Integer.cast() == nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -60,4 +60,42 @@ defmodule RDF.TimeTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "cast/1" do
|
||||
test "casting a time returns the input as it is" do
|
||||
assert RDF.time("01:00:00") |> RDF.Time.cast() ==
|
||||
RDF.time("01:00:00")
|
||||
end
|
||||
|
||||
test "casting a string" do
|
||||
assert RDF.string("01:00:00") |> RDF.Time.cast() ==
|
||||
RDF.time("01:00:00")
|
||||
assert RDF.string("01:00:00Z") |> RDF.Time.cast() ==
|
||||
RDF.time("01:00:00Z")
|
||||
assert RDF.string("01:00:00+01:00") |> RDF.Time.cast() ==
|
||||
RDF.time("01:00:00+01:00")
|
||||
end
|
||||
|
||||
test "casting a datetime" do
|
||||
assert RDF.date_time("2010-01-01T01:00:00") |> RDF.Time.cast() ==
|
||||
RDF.time("01:00:00")
|
||||
assert RDF.date_time("2010-01-01T00:00:00Z") |> RDF.Time.cast() ==
|
||||
RDF.time("00:00:00Z")
|
||||
assert RDF.date_time("2010-01-01T00:00:00+00:00") |> RDF.Time.cast() ==
|
||||
RDF.time("00:00:00Z")
|
||||
assert RDF.date_time("2010-01-01T23:00:00+01:00") |> RDF.Time.cast() ==
|
||||
RDF.time("23:00:00+01:00")
|
||||
end
|
||||
|
||||
test "with invalid literals" do
|
||||
assert RDF.time("25:00:00") |> RDF.Time.cast() == nil
|
||||
assert RDF.date_time("02010-01-01T00:00:00") |> RDF.Time.cast() == nil
|
||||
end
|
||||
|
||||
test "with literals of unsupported datatypes" do
|
||||
assert RDF.false |> RDF.Time.cast() == nil
|
||||
assert RDF.integer(1) |> RDF.Time.cast() == nil
|
||||
assert RDF.decimal(3.14) |> RDF.Time.cast() == nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue