[
https://issues.apache.org/jira/browse/JENA-1402?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16448024#comment-16448024
]
Bruno P. Kinoshita commented on JENA-1402:
------------------------------------------
At work we migrated a forecast system using Joda to Java 8 time API. Pretty
much everything worked, except some classes that were missing (two IIRC) that
were available in [three-thirteen|http://www.threeten.org/threeten-extra/]. 310
is the JSR number.
Perhaps there could be a third temporary/phase-out alternative... though it
could look a bit too hacky? One could create an adapter layer for Jena users to
experiment the Java 8 time package and see if that works OK before moving.
Add the following JVM argument when running the next class:
-Djavax.xml.datatype.DatatypeFactory=org.apache.jena.atlas.data.WrappedDurationDatatypeFactory.
{code:java}
// random module that I was reading the code...
package org.apache.jena.atlas.data;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
public class TestingXmlJava8Durations {
public static void main(String... args) throws
DatatypeConfigurationException {
String lex1 = "PT1M3.123S";
String lex2 = "PT0M10.123S";
DatatypeFactory factory = DatatypeFactory.newInstance();
System.out.println(factory.getClass()); // to get the factory class
name...
Duration dt1 = factory.newDuration(lex1);
Duration dt2 = factory.newDuration(lex2);
System.out.println(dt1);
System.out.println(dt2);
System.out.println();
Duration dt3 = dt1.subtract(dt2);
System.out.println(dt3);
System.out.println();
}
}
{code}
{code:java}
package org.apache.jena.atlas.data;
import java.math.BigDecimal;
import java.util.Calendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants.Field;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
public class WrappedXmlDuration extends Duration {
private java.time.Duration javaDuration;
private DatatypeFactory factory;
public WrappedXmlDuration(Duration xmlDuration) throws
DatatypeConfigurationException {
javaDuration =
java.time.Duration.ofMillis(xmlDuration.getTimeInMillis(Calendar.getInstance()));
factory =
DatatypeFactory.newInstance("org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl",
TestingXmlJava8Durations.class.getClassLoader());
}
public java.time.Duration getWrapped() {
return javaDuration;
}
@Override
public int getSign() {
if (javaDuration.isZero())
return 0;
return javaDuration.isNegative() ? -1 : 1;
}
@Override
public Number getField(Field field) {
throw new RuntimeException("Not implemented");
}
@Override
public boolean isSet(Field field) {
throw new RuntimeException("Not implemented");
}
@Override
public Duration add(Duration rhs) {
java.time.Duration otherDuration =
java.time.Duration.ofMillis(rhs.getTimeInMillis(Calendar.getInstance()));
java.time.Duration added = javaDuration.plus(otherDuration);
return factory.newDuration(added.toMillis());
}
@Override
public void addTo(Calendar calendar) {
throw new RuntimeException("Not implemented");
}
@Override
public Duration multiply(BigDecimal factor) {
java.time.Duration multiplied =
javaDuration.multipliedBy(factor.longValue());
return factory.newDuration(multiplied.toMillis());
}
@Override
public Duration negate() {
java.time.Duration negated = javaDuration.negated();
return factory.newDuration(negated.toMillis());
}
@Override
public Duration normalizeWith(Calendar startTimeInstant) {
throw new RuntimeException("Not implemented");
}
@Override
public int compare(Duration duration) {
java.time.Duration otherDuration = java.time.Duration
.ofMillis(duration.getTimeInMillis(Calendar.getInstance()));
return javaDuration.compareTo(otherDuration);
}
@Override
public int hashCode() {
return javaDuration.hashCode();
}
@Override
public String toString() {
return javaDuration.toString();
}
}
{code}
{code:java}
package org.apache.jena.atlas.data;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
public class WrappedDurationDatatypeFactory extends DatatypeFactory {
private DatatypeFactory factory;
public WrappedDurationDatatypeFactory() throws
DatatypeConfigurationException {
factory =
DatatypeFactory.newInstance("org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl",
TestingXmlJava8Durations.class.getClassLoader());
}
@Override
public Duration newDuration(String lexicalRepresentation) {
Duration wrappedDuration = factory.newDuration(lexicalRepresentation);
WrappedXmlDuration myDuration = null;
try {
myDuration = new WrappedXmlDuration(wrappedDuration);
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
return myDuration;
}
@Override
public Duration newDuration(long durationInMilliSeconds) {
Duration wrappedDuration = factory.newDuration(durationInMilliSeconds);
WrappedXmlDuration myDuration = null;
try {
myDuration = new WrappedXmlDuration(wrappedDuration);
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
return myDuration;
}
@Override
public Duration newDuration(boolean isPositive, BigInteger years,
BigInteger months, BigInteger days,
BigInteger hours, BigInteger minutes, BigDecimal seconds) {
Duration wrappedDuration = factory.newDuration(isPositive, years,
months, days, hours, minutes, seconds);
WrappedXmlDuration myDuration = null;
try {
myDuration = new WrappedXmlDuration(wrappedDuration);
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
return myDuration;
}
@Override
public XMLGregorianCalendar newXMLGregorianCalendar() {
throw new RuntimeException("Not implemented");
}
@Override
public XMLGregorianCalendar newXMLGregorianCalendar(String
lexicalRepresentation) {
throw new RuntimeException("Not implemented");
}
@Override
public XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal) {
throw new RuntimeException("Not implemented");
}
@Override
public XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year, int
month, int day, int hour, int minute,
int second, BigDecimal fractionalSecond, int timezone) {
throw new RuntimeException("Not implemented");
}
}
{code}
I read this ticket just before leaving $work, and kept wondering if that would
work... so had to have a crack at and see what would happen.
If you have the class in that package, or anywhere else in Eclipse, and start
Fuseki with the same JVM argument to replace the DatatypeFactory, you will get:
{noformat}
{
"head": {
"vars": [ "res" , "op1" , "op2" ]
} ,
"results": {
"bindings": [
{
"res": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT53.000S" } ,
"op1": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT2M3S" } ,
"op2": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1M10S" }
} ,
{
"res": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1M2.000S" } ,
"op1": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT2M3.123S" } ,
"op2": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1M1.123S" }
} ,
{
"res": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "-PT1M7.000S" } ,
"op1": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT0M3.123S" } ,
"op2": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1M10.123S" }
} ,
{
"res": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT53.000S" } ,
"op1": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT2M3.123S" } ,
"op2": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1M10.123S" }
} ,
{
"res": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1H3M53.000S" } ,
"op1": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT1H4M3.123S" } ,
"op2": { "type": "literal" , "datatype":
"http://www.w3.org/2001/XMLSchema#duration" , "value": "PT0M10.123S" }
}
]
}
}
{noformat}
Probably we would need the other methods implemented... but looks... doable?
Though not sure if a good idea...
Bruno
> Subtracting two xsd:Duration gives incorrect results in SPARQL query
> --------------------------------------------------------------------
>
> Key: JENA-1402
> URL: https://issues.apache.org/jira/browse/JENA-1402
> Project: Apache Jena
> Issue Type: Bug
> Components: ARQ
> Affects Versions: Jena 3.4.0
> Reporter: Greg Albiston
> Priority: Major
>
> There is an issue when subtracting two xsd:durations that include:
> * decimal seconds
> * non-zero minutes
> * second operand has a greater number of seconds than the first operand, i.e.
> the minutes are reduced.
> The result is a large number of minutes and incorrect seconds.
> For example:
> Integer, Larger: "PT2M3S" - "PT1M10S" = "PT0M53S" CORRECT
> Decimal, Smaller: "PT2M3.123S" - "PT1M1.123S" = "PT1M2.000S" CORRECT
> Decimal, Larger, Seconds: "PT0M3.123S" - "PT1M10.123S" = "-PT1M7.000S"
> CORRECT
> Decimal, Larger, Minutes: "PT2M3.123S" - "PT1M10.123S" = "PT883M0.020S"
> INCORRECT
> Decimal, Larger, Hours: "PT1H4M3.123S" - "PT0M10.123S" = "PT1H3883M0.020S"
> INCORRECT
> Example SPARQL:
> {code:sparql}
> SELECT ?res ?op1 ?op2
> WHERE{
> VALUES (?op1 ?op2) {
> ("PT2M3S"^^<http://www.w3.org/2001/XMLSchema#duration>
> "PT1M10S"^^<http://www.w3.org/2001/XMLSchema#duration>)
> ("PT2M3.123S"^^<http://www.w3.org/2001/XMLSchema#duration>
> "PT1M1.123S"^^<http://www.w3.org/2001/XMLSchema#duration>)
> ("PT0M3.123S"^^<http://www.w3.org/2001/XMLSchema#duration>
> "PT1M10.123S"^^<http://www.w3.org/2001/XMLSchema#duration>)
> ("PT2M3.123S"^^<http://www.w3.org/2001/XMLSchema#duration>
> "PT1M10.123S"^^<http://www.w3.org/2001/XMLSchema#duration>)
> ("PT1H4M3.123S"^^<http://www.w3.org/2001/XMLSchema#duration>
> "PT0M10.123S"^^<http://www.w3.org/2001/XMLSchema#duration>)
> }
> BIND(?op1 - ?op2 AS ?res)
> }
> {code}
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)