diff --git a/CHANGELOG.md b/CHANGELOG.md index 44ee2dd..e1b35d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ This project adheres to [Semantic Versioning](http://semver.org/) and ### Fixed +- `RDF.DateTime`: store microseconds - `RDF.DateTime`: '24:00:00' is a valid time in a xsd:dateTime; the dateTime value so represented is the first instant of the following day - `RDF.LangString`: non-strings or the empty string as language produce invalid diff --git a/lib/rdf/datatypes/date_time.ex b/lib/rdf/datatypes/date_time.ex index 44a7c8f..8ce9405 100644 --- a/lib/rdf/datatypes/date_time.ex +++ b/lib/rdf/datatypes/date_time.ex @@ -8,11 +8,11 @@ defmodule RDF.DateTime do # 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 |> strip_microseconds + 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 |> strip_microseconds + def convert(%NaiveDateTime{} = value, _), do: value def convert(value, opts) when is_binary(value) do case DateTime.from_iso8601(value) do @@ -54,11 +54,4 @@ defmodule RDF.DateTime do NaiveDateTime.to_iso8601(value) end - - # microseconds are not part of the xsd:dateTime value space - defp strip_microseconds(%{microsecond: ms} = date_time) when ms != {0, 0}, - do: %{date_time | microsecond: {0, 0}} - defp strip_microseconds(date_time), - do: date_time - end diff --git a/test/unit/datatypes/date_time_test.exs b/test/unit/datatypes/date_time_test.exs index a9e73ca..56dd304 100644 --- a/test/unit/datatypes/date_time_test.exs +++ b/test/unit/datatypes/date_time_test.exs @@ -3,21 +3,25 @@ defmodule RDF.DateTimeTest do use RDF.Datatype.Test.Case, datatype: RDF.DateTime, id: RDF.NS.XSD.dateTime, valid: %{ - # input => { value , lexical , canonicalized } - dt( "2010-01-01T00:00:00Z") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, - ~N[2010-01-01T00:00:00] => { dt( "2010-01-01T00:00:00") , nil , "2010-01-01T00:00:00" }, - ~N[2010-01-01T00:00:00.0000] => { dt( "2010-01-01T00:00:00") , nil , "2010-01-01T00:00:00" }, - dt("2010-01-01T00:00:00+00:00") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, - dt("2010-01-01T01:00:00+01:00") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, - dt("2009-12-31T23:00:00-01:00") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, - "2010-01-01T00:00:00Z" => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, - "2010-01-01T00:00:00.0000Z" => { dt( "2010-01-01T00:00:00Z") , "2010-01-01T00:00:00.0000Z", "2010-01-01T00:00:00Z" }, - "2010-01-01T00:00:00" => { dt( "2010-01-01T00:00:00") , nil , "2010-01-01T00:00:00" }, - "2010-01-01T00:00:00+00:00" => { dt( "2010-01-01T00:00:00Z") , "2010-01-01T00:00:00+00:00", "2010-01-01T00:00:00Z" }, - "2010-01-01T01:00:00+01:00" => { dt( "2010-01-01T00:00:00Z") , "2010-01-01T01:00:00+01:00", "2010-01-01T00:00:00Z" }, - "2009-12-31T23:00:00-01:00" => { dt( "2010-01-01T00:00:00Z") , "2009-12-31T23:00:00-01:00", "2010-01-01T00:00:00Z" }, - "2009-12-31T24:00:00" => { dt( "2010-01-01T00:00:00") , "2009-12-31T24:00:00" , "2010-01-01T00:00:00" }, - "2009-12-31T24:00:00+00:00" => { dt( "2010-01-01T00:00:00Z") , "2009-12-31T24:00:00+00:00", "2010-01-01T00:00:00Z" }, + # input => { value , lexical , canonicalized } + dt("2010-01-01T00:00:00Z") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, + ~N[2010-01-01T00:00:00] => { dt( "2010-01-01T00:00:00") , nil , "2010-01-01T00:00:00" }, + ~N[2010-01-01T00:00:00.00] => { dt( "2010-01-01T00:00:00.00") , nil , "2010-01-01T00:00:00.00" }, + ~N[2010-01-01T00:00:00.1234] => { dt( "2010-01-01T00:00:00.1234") , nil , "2010-01-01T00:00:00.1234" }, + dt("2010-01-01T00:00:00+00:00") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, + dt("2010-01-01T01:00:00+01:00") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, + dt("2009-12-31T23:00:00-01:00") => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, + dt("2009-12-31T23:00:00.00-01:00") => { dt( "2010-01-01T00:00:00.00Z") , nil , "2010-01-01T00:00:00.00Z" }, + "2010-01-01T00:00:00Z" => { dt( "2010-01-01T00:00:00Z") , nil , "2010-01-01T00:00:00Z" }, + "2010-01-01T00:00:00.0000Z" => { dt( "2010-01-01T00:00:00.0000Z") , nil, "2010-01-01T00:00:00.0000Z" }, + "2010-01-01T00:00:00.123456Z" => { dt( "2010-01-01T00:00:00.123456Z") , nil, "2010-01-01T00:00:00.123456Z" }, + "2010-01-01T00:00:00" => { dt( "2010-01-01T00:00:00") , nil , "2010-01-01T00:00:00" }, + "2010-01-01T00:00:00+00:00" => { dt( "2010-01-01T00:00:00Z") , "2010-01-01T00:00:00+00:00", "2010-01-01T00:00:00Z" }, + "2010-01-01T01:00:00+01:00" => { dt( "2010-01-01T00:00:00Z") , "2010-01-01T01:00:00+01:00", "2010-01-01T00:00:00Z" }, + "2009-12-31T23:00:00.42-01:00" => { dt( "2010-01-01T00:00:00.42Z") , "2009-12-31T23:00:00.42-01:00", "2010-01-01T00:00:00.42Z" }, + "2009-12-31T23:00:00-01:00" => { dt( "2010-01-01T00:00:00Z") , "2009-12-31T23:00:00-01:00", "2010-01-01T00:00:00Z" }, + "2009-12-31T24:00:00" => { dt( "2010-01-01T00:00:00") , "2009-12-31T24:00:00" , "2010-01-01T00:00:00" }, + "2009-12-31T24:00:00+00:00" => { dt( "2010-01-01T00:00:00Z") , "2009-12-31T24:00:00+00:00", "2010-01-01T00:00:00Z" }, # TODO: DateTime doesn't support negative years (at least with the iso8601 conversion functions) # "-2010-01-01T00:00:00Z" => { dt("-2010-01-01T00:00:00Z") , nil, "-2010-01-01T00:00:00Z" }, },