datetime arithmetic seems broken for some cases

1 view
Skip to first unread message

Conrad Leonard

unread,
Jun 26, 2015, 12:34:51 AM6/26/15
to sta...@clarkparsia.com
Subtracting dateTimes gives the expected results when the values differ in seconds, minutes, hours and days:

[conradL@qimr13054 ~]$ stardog query grafli "select ?d where { BIND(
'''2015-06-25T12:00:00Z'''^^xsd:dateTime -
'''2015-06-25T11:30:30Z'''^^xsd:dateTime as ?d) } " 
Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/opt/local/genomeinfo/java/truststore/keystore.jks
+------------------------------------------------------------------------+
|                                   d                                    |
+------------------------------------------------------------------------+
+------------------------------------------------------------------------+

Query returned 1 results in 00:00:00.051
[conradL@qimr13054 ~]$ stardog query grafli "select ?d where { BIND(
'''2015-06-25T12:00:00Z'''^^xsd:dateTime -
'''2015-06-24T12:00:00Z'''^^xsd:dateTime as ?d) } " 
Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/opt/local/genomeinfo/java/truststore/keystore.jks
+----------------------------------------------------------------------+
|                                  d                                   |
+----------------------------------------------------------------------+
+----------------------------------------------------------------------+


but not for months and years:
Query returned 1 results in 00:00:00.049
[conradL@qimr13054 ~]$ stardog query grafli "select ?d where { BIND(
'''2015-06-25T12:00:00Z'''^^xsd:dateTime - 
'''2015-05-25T12:00:00Z'''^^xsd:dateTime as ?d) } " 
Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/opt/local/genomeinfo/java/truststore/keystore.jks
+----------------------------------------------------------------------+
|                                  d                                   |
+----------------------------------------------------------------------+
+----------------------------------------------------------------------+

Query returned 1 results in 00:00:00.043
[conradL@qimr13054 ~]$ stardog query grafli "select ?d where { BIND(
'''2015-06-25T12:00:00Z'''^^xsd:dateTime - 
'''2014-06-25T12:00:00Z'''^^xsd:dateTime as ?d) } " 
Picked up JAVA_TOOL_OPTIONS: -Djavax.net.ssl.trustStore=/opt/local/genomeinfo/java/truststore/keystore.jks
+----------------------------------------------------------------------+
|                                  d                                   |
+----------------------------------------------------------------------+
+----------------------------------------------------------------------+

I would expect the last two to return P31DT0H0M0.000S and P365DT0H0M0.000S respectively.

Michael Grove

unread,
Jun 26, 2015, 12:20:23 PM6/26/15
to stardog
So this turns out to be a bug or really unfortunate behavior in Sun's implementation of `javax.xml.datatype.DatatypeFactory`.

The default implementation is `com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl`.  The functions for doing the dateTime math use `DatatypeFactory#newDurationDayTime` which returns for an input of `32` days, a duration which has zero months and 1 day.  From the javadocs [1] I can see that the expected value does not have a month component, so zero for the months seems fine, but in that case, I'd expect `32` as the number of days.  If you use xerces directly(org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl), this is the value you get.

The javadocs don't specify, but it's possible the sun implementation is fine if the contract is that durations >= one month are not supported.  But that'd be really unfortunate if it's the case.

I've created an issue for this, #2373.  In the meantime, there's a reasonably simple workaround.  Download the xerces implementation from [2], drop it into $STARDOG/server/dbms and add the JVM argument `-Djavax.xml.datatype.DatatypeFactory=org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl` -- easiest thing there is to just edit the stardog-admin script.  Then on restart the server will use the xerces implementation and you'll get the expected results.

Cheers,

Mike

 


--
-- --
You received this message because you are subscribed to the C&P "Stardog" group.
To post to this group, send email to sta...@clarkparsia.com
To unsubscribe from this group, send email to
stardog+u...@clarkparsia.com
For more options, visit this group at
http://groups.google.com/a/clarkparsia.com/group/stardog?hl=en

Conrad Leonard

unread,
Jun 26, 2015, 7:55:26 PM6/26/15
to sta...@clarkparsia.com
Yeah wow that is... odd. I'd say it's a bug by the definition of failing to meet reasonable expectations if not documentation, which as you say is lacking. Thanks as always for the detailed explanation and workaround.

cheers,
Conrad.

Rob Vesse

unread,
Jun 29, 2015, 5:00:03 AM6/29/15
to Stardog Mailing List

From: Michael Grove <mi...@complexible.com>

The javadocs don't specify, but it's possible the sun implementation is fine if the contract is that durations >= one month are not supported.  But that'd be really unfortunate if it's the case.

Yep that is the case, XML Schema Datatypes has multiples types for duration

For xsd:dayTimeDuration as used in these example it states "The ·value space· of dayTimeDuration is therefore that of duration restricted to those whose ·months· property is 0"


And in fact actually goes on to say that year and month components are illegal in the lexical representation

If you need a more general duration you likely want to use the super-type xsd:duration which does support years and months

Rob

Conrad Leonard

unread,
Jun 29, 2015, 7:49:12 AM6/29/15
to sta...@clarkparsia.com
I would still say it is a bug in the sun implementation of newDurationDayTime. It is clear from the W3C spec that dayTimeDuration has no year or month parts but I don't think that has any bearing here; if you supply a millisecond value greater than 31D you should get back the correct dayTimeDuration representation of the duration in days, hours, minutes and seconds, not the modulus arithmetic value. There is nothing in W3C spec that says 31D should be the upper bound of dayTimeDuration. My take on that spec is that the whole point of the datatype is that it is an _ordered_ duration type that can unambiguously describe arbitrary dateTime differences (see the note on partial ordering here http://www.w3.org/TR/2012/REC-xmlschema11-2-20120405/datatypes.html#duration). The fact that xerces implementation interprets it this way lends weight to this I think.

<edited to correct a misapprehension on my part as to what DatatypeFactory was doing>

Conrad Leonard

unread,
Jun 29, 2015, 9:27:48 AM6/29/15
to sta...@clarkparsia.com
Not that it matters really, but at the very least, the sun impl is inconsistent in the way it treats the millisecond (long) and lexical (String) signatures of newDurationDayTime:
groovy:000> import javax.xml.datatype.DatatypeFactory
===> javax.xml.datatype.DatatypeFactory
groovy:000> f = DatatypeFactory.newInstance()
===> com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl@e70f13a
groovy:000> du32D = f.newDurationDayTime('P32DT0H0M0.000S')
===> P32DT0H0M0.000S
groovy:000> du32Dms = (long)(du32D.getValue() * 1000)
groovy:000> f.newDurationDayTime(du32Dms)
===> P1DT0H0M0.000S

Reply all
Reply to author
Forward
0 new messages