Handle derived datatypes on RDF.Literal.Datatype.compare/2 properly

This commit is contained in:
Marcel Otto 2020-05-27 00:56:44 +02:00
parent 162e82ed47
commit 98adbaf878
13 changed files with 154 additions and 153 deletions

View file

@ -130,20 +130,23 @@ defmodule RDF.Literal.Datatype do
@callback do_equal_value_different_datatypes?(literal, literal) :: boolean | nil
@doc """
Compares two `RDF.Literal`s.
Callback for datatype specific `compare/2` comparisons between two `RDF.Literal`s.
Returns `:gt` if value of the first literal is greater than the value of the second in
terms of their datatype and `:lt` for vice versa. If the two literals are equal `:eq` is returned.
For datatypes with only partial ordering `:indeterminate` is returned when the
This callback is called by auto-generated `compare/2` function on the implementations, which already deals with the basic cases.
So, implementations can assume the passed arguments are valid `RDF.Literal.Datatype` structs and
have the same datatypes or are derived from each other.
Should return `:gt` if value of the first literal is greater than the value of the second in
terms of their datatype and `:lt` for vice versa. If the two literals can be considered equal `:eq` should be returned.
For datatypes with only partial ordering `:indeterminate` should be returned when the
order of the given literals is not defined.
Returns `nil` when the given arguments are not comparable datatypes or if one
them is invalid.
`nil` should be returned when the given arguments are not comparable datatypes or if one them is invalid.
The default implementation of the `_using__` macro of `RDF.XSD.Datatype`s
compares the values of the `canonical/1` forms of the given literals of this datatype.
The default implementation of the `_using__` macro of `RDF.Literal.Datatype`s
just compares the values of the given literals.
"""
@callback compare(Literal.t() | literal, Literal.t() | literal) :: comparison_result | :indeterminate | nil
@callback do_compare(literal, literal) :: comparison_result | :indeterminate | nil
@doc """
Updates the value of a `RDF.Literal` without changing everything else.
@ -348,7 +351,37 @@ defmodule RDF.Literal.Datatype do
defp resource?(%RDF.BlankNode{}), do: true
defp resource?(_), do: false
@impl unquote(__MODULE__)
# RDF.XSD.Datatypes offers another default implementation, but since it is
# still in a macro implementation defoverridable doesn't work
unless RDF.XSD.Datatype in @behaviour do
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(left, right) do
if Literal.datatype?(left) and Literal.datatype?(right) and
Literal.Datatype.valid?(left) and Literal.Datatype.valid?(right) do
do_compare(left, right)
end
end
@impl RDF.Literal.Datatype
def do_compare(%datatype{} = left, %datatype{} = right) do
case {datatype.value(left), datatype.value(right)} do
{left_value, right_value} when left_value < right_value -> :lt
{left_value, right_value} when left_value > right_value -> :gt
_ ->
if datatype.equal_value?(left, right), do: :eq
end
end
def do_compare(_, _), do: nil
defoverridable compare: 2,
do_compare: 2
end
@impl unquote(__MODULE__)
def update(literal, fun, opts \\ [])
def update(%Literal{literal: literal}, fun, opts), do: update(literal, fun, opts)
def update(%__MODULE__{} = literal, fun, opts) do

View file

@ -92,21 +92,17 @@ defmodule RDF.Literal.Generic do
def do_equal_value_same_or_derived_datatypes?(_, _), do: nil
@impl Datatype
def compare(left, %Literal{literal: right}), do: compare(left, right)
def compare(%Literal{literal: left}, right), do: compare(left, right)
def compare(%__MODULE__{datatype: datatype} = literal1,
%__MODULE__{datatype: datatype} = literal2) do
if valid?(literal1) and valid?(literal2) do
case {literal1.value, literal2.value} do
{value1, value2} when value1 < value2 -> :lt
{value1, value2} when value1 > value2 -> :gt
_ ->
if equal_value?(literal1, literal2), do: :eq
end
def do_compare(%__MODULE__{datatype: datatype} = left_literal,
%__MODULE__{datatype: datatype} = right_literal) do
case {left_literal.value, right_literal.value} do
{left_value, right_value} when left_value < right_value -> :lt
{left_value, right_value} when left_value > right_value -> :gt
_ ->
if equal_value?(left_literal, right_literal), do: :eq
end
end
def compare(_, _), do: nil
def do_compare(_, _), do: nil
@impl Datatype
def update(literal, fun, opts \\ [])

View file

@ -78,23 +78,6 @@ defmodule RDF.LangString do
@impl Datatype
def do_cast(_), do: nil
@impl Datatype
def compare(left, %Literal{literal: right}), do: compare(left, right)
def compare(%Literal{literal: left}, right), do: compare(left, right)
def compare(%__MODULE__{language: language_tag} = literal1,
%__MODULE__{language: language_tag} = literal2) do
if valid?(literal1) and valid?(literal2) do
case {canonical(literal1).literal.value, canonical(literal2).literal.value} do
{value1, value2} when value1 < value2 -> :lt
{value1, value2} when value1 > value2 -> :gt
_ ->
if equal_value?(literal1, literal2), do: :eq
end
end
end
def compare(_, _), do: nil
@impl Datatype
def update(literal, fun, opts \\ [])
def update(%Literal{literal: literal}, fun, opts), do: update(literal, fun, opts)

View file

@ -13,8 +13,6 @@ defmodule RDF.XSD.Datatype do
:uncanonical_lexical => uncanonical_lexical()
}
@type comparison_result :: :lt | :gt | :eq
import RDF.Utils.Guards
@doc """
@ -272,6 +270,17 @@ defmodule RDF.XSD.Datatype do
end
end
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(left, right) do
if RDF.XSD.datatype?(left) and RDF.XSD.datatype?(right) and
RDF.Literal.Datatype.valid?(left) and RDF.Literal.Datatype.valid?(right) do
do_compare(left, right)
end
end
defimpl Inspect do
"Elixir.Inspect." <> datatype_name = to_string(__MODULE__)
@datatype_name datatype_name

View file

@ -56,24 +56,19 @@ defmodule RDF.XSD.Datatype.Primitive do
@impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: nil
@impl RDF.Literal.Datatype
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(
%__MODULE__{value: left_value} = left,
%__MODULE__{value: right_value} = right
)
when not (is_nil(left_value) or is_nil(right_value)) do
case {left |> canonical() |> value(), right |> canonical() |> value()} do
{value1, value2} when value1 < value2 -> :lt
{value1, value2} when value1 > value2 -> :gt
_ -> if equal_value?(left, right), do: :eq
@impl RDF.Literal.Datatype
def do_compare(%left_datatype{} = left, %right_datatype{} = right) do
if left_datatype.datatype?(right_datatype) or right_datatype.datatype?(left_datatype) do
case {left_datatype.value(left), right_datatype.value(right)} do
{left_value, right_value} when left_value < right_value -> :lt
{left_value, right_value} when left_value > right_value -> :gt
_ ->
if left_datatype.equal_value?(left, right), do: :eq
end
end
end
def compare(_, _), do: nil
def do_compare(_, _), do: nil
defoverridable canonical_mapping: 1,
do_cast: 1,
@ -81,7 +76,7 @@ defmodule RDF.XSD.Datatype.Primitive do
init_invalid_lexical: 2,
do_equal_value_same_or_derived_datatypes?: 2,
do_equal_value_different_datatypes?: 2,
compare: 2
do_compare: 2
@before_compile unquote(__MODULE__)
end

View file

@ -86,14 +86,14 @@ defmodule RDF.XSD.Datatype.Restriction do
end
@impl RDF.Literal.Datatype
def compare(left, right), do: @base.compare(left, right)
def do_compare(left, right), do: @base.do_compare(left, right)
defoverridable canonical_mapping: 1,
do_cast: 1,
equal_value?: 2,
do_equal_value_same_or_derived_datatypes?: 2,
do_equal_value_different_datatypes?: 2,
compare: 2
do_compare: 2
Module.register_attribute(__MODULE__, :facets, accumulate: true)

View file

@ -183,21 +183,7 @@ defmodule RDF.XSD.Date do
end
@impl RDF.Literal.Datatype
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
def compare(
%__MODULE__{value: value1},
%__MODULE__{value: value2}
)
when is_nil(value1) or is_nil(value2),
do: nil
def compare(
%__MODULE__{value: value1},
%__MODULE__{value: value2}
) do
def do_compare(%{value: value1}, %{value: value2}) do
XSD.DateTime.compare(
comparison_normalization(value1),
comparison_normalization(value2)
@ -209,27 +195,27 @@ defmodule RDF.XSD.Date do
# ordering comparisons in the date-3 test. The following implementation would allow
# an ordering comparisons between date and datetimes.
#
# def compare(
# def do_compare(
# %__MODULE__{value: date_value},
# %XSD.DateTime{} = datetime_literal
# ) do
# XSD.DateTime.compare(
# comparison_normalization(date_value),
# comparison_normalization(date_value).literal,
# datetime_literal
# )
# end
#
# def compare(
# def do_compare(
# %XSD.DateTime{} = datetime_literal,
# %__MODULE__{value: date_value}
# ) do
# XSD.DateTime.compare(
# XSD.DateTime.do_compare(
# datetime_literal,
# comparison_normalization(date_value)
# comparison_normalization(date_value).literal
# )
# end
def compare(_, _), do: nil
def do_compare(_, _), do: nil
defp comparison_normalization({date, tz}) do
(Date.to_iso8601(date) <> "T00:00:00" <> tz)

View file

@ -185,15 +185,10 @@ defmodule RDF.XSD.DateTime do
end
end
@impl RDF.Literal.Datatype
def compare(left, right)
def compare(left, %RDF.Literal{literal: right}), do: compare(left, right)
def compare(%RDF.Literal{literal: left}, right), do: compare(left, right)
@impl RDF.Literal.Datatype
def do_compare(left, right)
def compare(
%__MODULE__{value: %type{} = value1},
%__MODULE__{value: %type{} = value2}
) do
def do_compare(%{value: %type{} = value1}, %{value: %type{} = value2}) do
type.compare(value1, value2)
end
@ -202,37 +197,31 @@ defmodule RDF.XSD.DateTime do
# ordering comparisons in the date-3 test. The following implementation would allow
# an ordering comparisons between date and datetimes.
#
# def compare(%__MODULE__{} = literal1, %XSD.Date{} = literal2) do
# XSD.Date.compare(literal1, literal2)
# def do_compare(%__MODULE__{} = literal1, %XSD.Date{} = literal2) do
# XSD.Date.do_compare(literal1, literal2)
# end
#
# def compare(%XSD.Date{} = literal1, %__MODULE__{} = literal2) do
# XSD.Date.compare(literal1, literal2)
# def do_compare(%XSD.Date{} = literal1, %__MODULE__{} = literal2) do
# XSD.Date.do_compare(literal1, literal2)
# end
def compare(
%__MODULE__{value: %DateTime{}} = left,
%__MODULE__{value: %NaiveDateTime{} = right_value}
) do
def do_compare(%{value: %DateTime{}} = left, %{value: %NaiveDateTime{} = right_value}) do
cond do
compare(left, new(to_datetime(right_value, "+"))) == :lt -> :lt
compare(left, new(to_datetime(right_value, "-"))) == :gt -> :gt
do_compare(left, new(to_datetime(right_value, "+")).literal) == :lt -> :lt
do_compare(left, new(to_datetime(right_value, "-")).literal) == :gt -> :gt
true -> :indeterminate
end
end
def compare(
%__MODULE__{value: %NaiveDateTime{} = left},
%__MODULE__{value: %DateTime{}} = right_literal
) do
def do_compare(%{value: %NaiveDateTime{} = left}, %{value: %DateTime{}} = right_literal) do
cond do
compare(new(to_datetime(left, "-")), right_literal) == :lt -> :lt
compare(new(to_datetime(left, "+")), right_literal) == :gt -> :gt
do_compare(new(to_datetime(left, "-")).literal, right_literal) == :lt -> :lt
do_compare(new(to_datetime(left, "+")).literal, right_literal) == :gt -> :gt
true -> :indeterminate
end
end
def compare(_, _), do: nil
def do_compare(_, _), do: nil
defp to_datetime(naive_datetime, offset) do
(NaiveDateTime.to_iso8601(naive_datetime) <> offset <> "14:00")

View file

@ -153,14 +153,14 @@ defmodule RDF.XSD.Decimal do
@impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right)
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right)
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def compare(left, right), do: XSD.Numeric.compare(left, right)
def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
@doc """
The number of digits in the XML Schema canonical form of the literal value.

View file

@ -161,12 +161,12 @@ defmodule RDF.XSD.Double do
@impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right)
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right)
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def compare(left, right), do: XSD.Numeric.compare(left, right)
def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
end

View file

@ -100,13 +100,13 @@ defmodule RDF.XSD.Integer do
end
@impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right)
def do_equal_value_same_or_derived_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.equal_value?(left, right)
def do_equal_value_different_datatypes?(left, right), do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def compare(left, right), do: XSD.Numeric.compare(left, right)
def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
@doc """
The number of digits in the XML Schema canonical form of the literal value.

View file

@ -20,10 +20,10 @@ defmodule RDF.XSD.Numeric do
- <https://www.w3.org/TR/sparql11-query/#OperatorMapping>
- <https://www.w3.org/TR/xpath-functions/#func-numeric-equal>
"""
@spec equal_value?(t() | any, t() | any) :: boolean
def equal_value?(left, right)
@spec do_equal_value?(t() | any, t() | any) :: boolean
def do_equal_value?(left, right)
def equal_value?(%left_datatype{value: left}, %right_datatype{value: right}) do
def do_equal_value?(%left_datatype{value: left}, %right_datatype{value: right}) do
cond do
XSD.Decimal.datatype?(left_datatype) or XSD.Decimal.datatype?(right_datatype) ->
equal_decimal_value?(left, right)
@ -36,7 +36,7 @@ defmodule RDF.XSD.Numeric do
end
end
def equal_value?(_, _), do: nil
def do_equal_value?(_, _), do: nil
defp equal_decimal_value?(%D{} = left, %D{} = right), do: D.equal?(left, right)
@ -51,7 +51,7 @@ defmodule RDF.XSD.Numeric do
defp new_decimal(value) when is_float(value), do: D.from_float(value)
defp new_decimal(value), do: D.new(value)
@doc """
@doc !"""
Compares two numeric XSD literals.
Returns `:gt` if first literal is greater than the second and `:lt` for vice
@ -60,36 +60,14 @@ defmodule RDF.XSD.Numeric do
Returns `nil` when the given arguments are not comparable datatypes.
"""
@spec compare(Literal.t | t, Literal.t | t) :: XSD.Datatype.comparison_result() | nil
def compare(left, right)
def compare(left, %Literal{literal: right}), do: compare(left, right)
def compare(%Literal{literal: left}, right), do: compare(left, right)
@spec do_compare(t, t) :: Literal.Datatype.comparison_result() | nil
def do_compare(left, right)
def compare(
%XSD.Decimal{value: left},
%right_datatype{value: right}
) do
if datatype?(right_datatype) do
compare_decimal_value(left, right)
end
end
def compare(
%left_datatype{value: left},
%XSD.Decimal{value: right}
) do
if datatype?(left_datatype) do
compare_decimal_value(left, right)
end
end
def compare(
%left_datatype{value: left},
%right_datatype{value: right}
)
when not (is_nil(left) or is_nil(right)) do
def do_compare(%left_datatype{value: left}, %right_datatype{value: right}) do
if datatype?(left_datatype) and datatype?(right_datatype) do
cond do
XSD.Decimal.datatype?(left_datatype) or XSD.Decimal.datatype?(right_datatype) ->
compare_decimal_value(left, right)
left < right -> :lt
left > right -> :gt
true -> :eq
@ -97,7 +75,7 @@ defmodule RDF.XSD.Numeric do
end
end
def compare(_, _), do: nil
def do_compare(_, _), do: nil
defp compare_decimal_value(%D{} = left, %D{} = right), do: D.cmp(left, right)

View file

@ -2,6 +2,7 @@ defmodule RDF.XSD.ComparisonTest do
use ExUnit.Case
alias RDF.XSD
alias RDF.TestDatatypes.{Initials, Age, DecimalUnitInterval, CustomTime, DateWithoutTz, DateTimeWithTz}
describe "XSD.String" do
@ordered_strings [
@ -17,6 +18,13 @@ defmodule RDF.XSD.ComparisonTest do
assert_equal({XSD.string("foo"), XSD.string("foo")})
end
test "valid comparisons between derived string literals" do
assert_equal({Initials.new("fo"), XSD.string("fo")})
assert_order({Initials.new("ba"), Initials.new("fo")})
assert_order({Initials.new("ba"), XSD.string("foo")})
assert_order({XSD.string("bar"), Initials.new("fo")})
end
test "invalid comparison between string and langString literals" do
assert_incomparable({XSD.string("foo"), RDF.langString("foo", :en)})
end
@ -50,7 +58,14 @@ defmodule RDF.XSD.ComparisonTest do
{XSD.non_negative_integer(0), XSD.integer(1)},
{XSD.integer(0), XSD.positive_integer(1)},
{XSD.non_negative_integer(0), XSD.positive_integer(1)},
{XSD.positive_integer(1), XSD.non_negative_integer(2)}
{XSD.positive_integer(1), XSD.non_negative_integer(2)},
{XSD.positive_integer(1), XSD.non_negative_integer(2)},
{Age.new(1), Age.new(2)},
{Age.new(1), XSD.integer(2)},
{XSD.non_negative_integer(1), Age.new(2)},
{Age.new(1), XSD.decimal(2.1)},
{XSD.decimal(0.1), DecimalUnitInterval.new(0.2)},
{DecimalUnitInterval.new(0.3), Age.new(2)},
],
&assert_order/1
)
@ -89,6 +104,7 @@ defmodule RDF.XSD.ComparisonTest do
)
assert_order({XSD.datetime("2000-01-15T12:00:00"), XSD.datetime("2000-01-16T12:00:00Z")})
assert_order({XSD.datetime("2000-01-15T12:00:00"), DateTimeWithTz.new("2000-01-16T12:00:00Z")})
end
test "when unequal due to missing time zone" do
@ -110,6 +126,10 @@ defmodule RDF.XSD.ComparisonTest do
{XSD.datetime("2002-04-02T23:00:00-04:00"), XSD.datetime("2002-04-03T02:00:00-01:00")}
)
assert_equal(
{DateTimeWithTz.new("2002-04-02T23:00:00-04:00"), XSD.datetime("2002-04-03T02:00:00-01:00")}
)
assert_equal({XSD.datetime("1999-12-31T24:00:00"), XSD.datetime("2000-01-01T00:00:00")})
# TODO: Assume that the dynamic context provides an implicit timezone value of -05:00
# assert_equal {XSD.datetime("2002-04-02T12:00:00"), XSD.datetime("2002-04-02T23:00:00+06:00")}
@ -127,6 +147,10 @@ defmodule RDF.XSD.ComparisonTest do
assert_indeterminate(
{XSD.datetime("2000-01-16T00:00:00"), XSD.datetime("2000-01-16T12:00:00Z")}
)
assert_indeterminate(
{XSD.datetime("2000-01-16T00:00:00"), DateTimeWithTz.new("2000-01-16T12:00:00Z")}
)
end
end
@ -135,6 +159,8 @@ defmodule RDF.XSD.ComparisonTest do
assert_order({XSD.date("2002-04-02"), XSD.date("2002-04-03")})
assert_order({XSD.date("2002-04-02+01:00"), XSD.date("2002-04-03+00:00")})
assert_order({XSD.date("2002-04-02"), XSD.date("2002-04-03Z")})
assert_order({DateWithoutTz.new("2002-04-02"), XSD.date("2002-04-03Z")})
assert_order({DateWithoutTz.new("2002-04-02"), DateWithoutTz.new("2002-04-03")})
end
test "when equal" do
@ -143,12 +169,14 @@ defmodule RDF.XSD.ComparisonTest do
assert_equal({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02+00:00")})
assert_equal({XSD.date("2002-04-02Z"), XSD.date("2002-04-02+00:00")})
assert_equal({XSD.date("2002-04-02Z"), XSD.date("2002-04-02-00:00")})
assert_equal({XSD.date("2002-04-02"), DateWithoutTz.new("2002-04-02")})
end
test "when indeterminate" do
assert_indeterminate({XSD.date("2002-04-02Z"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02+00:00"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02Z"), DateWithoutTz.new("2002-04-02")})
end
end
@ -187,18 +215,21 @@ defmodule RDF.XSD.ComparisonTest do
test "when unequal" do
assert_order({XSD.time("12:00:00+01:00"), XSD.time("13:00:00+01:00")})
assert_order({XSD.time("12:00:00"), XSD.time("13:00:00")})
assert_order({CustomTime.new("12:00:00"), CustomTime.new("13:00:00")})
end
test "when equal" do
assert_equal({XSD.time("12:00:00+01:00"), XSD.time("12:00:00+01:00")})
assert_equal({XSD.time("12:00:00"), XSD.time("12:00:00")})
assert_equal({CustomTime.new("12:00:00+01:00"), XSD.time("12:00:00+01:00")})
end
test "when indeterminate" do
assert_indeterminate({XSD.date("2002-04-02Z"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02+00:00"), XSD.date("2002-04-02")})
assert_indeterminate({XSD.date("2002-04-02-00:00"), XSD.date("2002-04-02")})
end
# TODO:
# test "when indeterminate" do
# assert_indeterminate({XSD.time("12:00:00Z"), XSD.time("12:00:00")})
# assert_indeterminate({XSD.time("12:00:00+00:00"), XSD.time("12:00:00")})
# assert_indeterminate({XSD.time("12:00:00-00:00"), XSD.time("12:00:00")})
# end
end
describe "incomparable" do
@ -231,6 +262,7 @@ defmodule RDF.XSD.ComparisonTest do
Enum.each(
[
{XSD.true(), XSD.boolean(42)},
{XSD.false(), Age.new(242)},
{XSD.datetime("2002-04-02T12:00:00"), XSD.datetime("2002.04.02 12:00")},
{XSD.date("2002-04-02"), XSD.date("2002.04.02")},
{XSD.time("12:00:00"), XSD.time("12-00-00")}