This is an automated email from the ASF dual-hosted git repository. andy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/jena.git
commit a2dd5b0acf165d98f128cf1c0f43fb9ec004f3b5 Author: Andy Seaborne <[email protected]> AuthorDate: Sat Feb 17 17:25:54 2024 +0000 GH-2273: Implement XSD duration divide operations --- .../jena/sparql/expr/nodevalue/NodeValueOps.java | 169 ++++++------ .../apache/jena/sparql/expr/TestNodeValueOps.java | 300 +++++++++++++++------ 2 files changed, 300 insertions(+), 169 deletions(-) diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java index 88d6b86378..3a36dc9040 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java @@ -18,88 +18,38 @@ package org.apache.jena.sparql.expr.nodevalue; -import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED ; -import static org.apache.jena.datatypes.xsd.XSDDatatype.XSD ; -import static org.apache.jena.sparql.expr.ValueSpace.* ; +import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED; +import static org.apache.jena.sparql.expr.ValueSpace.*; -import java.math.BigDecimal ; -import java.util.GregorianCalendar ; +import java.math.BigDecimal; +import java.util.GregorianCalendar; -import javax.xml.datatype.Duration ; -import javax.xml.datatype.XMLGregorianCalendar ; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; -import org.apache.jena.datatypes.xsd.XSDDatatype ; -import org.apache.jena.graph.Node ; -import org.apache.jena.sparql.expr.ExprEvalTypeException ; -import org.apache.jena.sparql.expr.NodeValue ; -import org.apache.jena.sparql.expr.ValueSpace ; -import org.apache.jena.sparql.util.NodeFactoryExtra ; +import org.apache.jena.datatypes.xsd.XSDDatatype; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.NodeFactory; +import org.apache.jena.sparql.expr.ExprEvalTypeException; +import org.apache.jena.sparql.expr.NodeValue; +import org.apache.jena.sparql.expr.ValueSpace; /** The code parts of arithmetic operations on {@link NodeValue}s. */ public class NodeValueOps { - /* Date/time/duration coverage - * add, subtract (duration, duration) - * -(xsd:duration, xsd:duration) -> xsd:duration - 10.6.1 op:add-yearMonthDurations - 10.6.2 op:subtract-yearMonthDurations -(xsd:duration, xsd:duration) -> xsd:duration - 10.6.6 op:add-dayTimeDurations - 10.6.7 op:subtract-dayTimeDurations -** Java has general duration subtract - - * Subtract two date/times - -(xsd:dateTime, xsd:dateTime) -> xsd:duration - 10.8.1 op:subtract-dateTimes -> xsd:dayTimeDuration -(xsd:date, xsd:date) -> xsd:duration - 10.8.2 op:subtract-dates -(xsd:time, xsd:time) -> xsd:duration - 10.8.3 op:subtract-times - - * Date/time and duration -** Java has general duration subtract (error needed?) - -(xsd:dateTime, xsd:duration) -> xsd:dateTime - 10.8.4 op:add-yearMonthDuration-to-dateTime - 10.8.5 op:add-dayTimeDuration-to-dateTime - 10.8.6 op:subtract-yearMonthDuration-from-dateTime - 10.8.7 op:subtract-dayTimeDuration-from-dateTime - -(xsd:date, xsd:duration) -> xsd:date - 10.8.8 op:add-yearMonthDuration-to-date - 10.8.9 op:add-dayTimeDuration-to-date - 10.8.10 op:subtract-yearMonthDuration-from-date - 10.8.11 op:subtract-dayTimeDuration-from-date - -(xsd:time, xsd:duration) -> xsd:time - 10.8.12 op:add-dayTimeDuration-to-time - 10.8.13 op:subtract-dayTimeDuration-from-time - -(xsd:duration, xsd:double) -> xsd:duration - 10.6.8 op:multiply-dayTimeDuration - */ - - /* Missing: -(xsd:duration, xsd:double) -> xsd:duration - 10.6.9 op:divide-dayTimeDuration - -(xsd:duration, xsd:duration) -> xsd:decimal - 10.6.10 op:divide-dayTimeDuration-by-dayTimeDuration - */ - /* Notes: - * Does not consider whether a duration is dayTime or yearMonth - * for addition and subtraction. + /* + * Notes: + * Does not consider whether a duration is dayTime or yearMonth for + * multiplication and division where the operation can changes the result type. * As per the Java (Xerces) implementation, it just work on durations. */ - // Until part of Jena datatypes. - private static final String dtXSDdateTimeStamp = XSD+"#dateTimeStamp" ; - private static final String dtXSDdayTimeDuration = XSD+"#dayTimeDuration" ; - private static final String dtXSDyearMonthDuration = XSD+"#yearMonthDuration" ; + //private static final String dtXSDdateTimeStamp = XSDDatatype.XSDdateTimeStamp.getURI(); + private static final String dtXSDdayTimeDuration = XSDDatatype.XSDdayTimeDuration.getURI(); + private static final String dtXSDyearMonthDuration = XSDDatatype.XSDyearMonthDuration.getURI(); + /** Add two {@link NodeValue NodeValues}, with all the extra datatypes and extensions supported. */ public static NodeValue additionNV(NodeValue nv1, NodeValue nv2) { ValueSpace vs1 = nv1.getValueSpace(); ValueSpace vs2 = nv2.getValueSpace(); @@ -117,11 +67,11 @@ public class NodeValueOps String lex = d3.toString(); Node n; if ( isDTDur ) - n = NodeFactoryExtra.createLiteralNode(lex, null, dtXSDdayTimeDuration); + n = NodeFactory.createLiteral(lex, XSDDatatype.XSDdayTimeDuration); else if ( isYMDur ) - n = NodeFactoryExtra.createLiteralNode(lex, null, dtXSDyearMonthDuration); + n = NodeFactory.createLiteral(lex, XSDDatatype.XSDyearMonthDuration); else - n = org.apache.jena.graph.NodeFactory.createLiteral(lex, XSDDatatype.XSDduration); + n = NodeFactory.createLiteral(lex, XSDDatatype.XSDduration); return NodeValue.makeNodeDuration(d3, n); } @@ -147,14 +97,10 @@ public class NodeValueOps NodeValue r = NodeValue.makeNode(result.toXMLFormat(), XSDDatatype.XSDtime); return r; } - - if ( isDT(vs2) && vs1.equals(VSPACE_DURATION) ) - // Carefully ... - return additionNV(nv2, nv1); throw new ExprEvalTypeException("Operator '+' : Undefined addition: " + nv1 + " and " + nv2); } - // NodeFunctions + /** Subtract two {@link NodeValue NodeValues}, with all the extra datatypes and extensions supported. */ public static NodeValue subtractionNV(NodeValue nv1, NodeValue nv2) { ValueSpace vs1 = nv1.getValueSpace(); ValueSpace vs2 = nv2.getValueSpace(); @@ -170,9 +116,9 @@ public class NodeValueOps String lex = d3.toString(); Node n; if ( isDTDur ) - n = NodeFactoryExtra.createLiteralNode(lex, null, dtXSDdayTimeDuration); + n = NodeFactory.createLiteral(lex, XSDDatatype.XSDdayTimeDuration); else if ( isYMDur ) - n = NodeFactoryExtra.createLiteralNode(lex, null, dtXSDyearMonthDuration); + n = NodeFactory.createLiteral(lex, XSDDatatype.XSDyearMonthDuration); else n = org.apache.jena.graph.NodeFactory.createLiteral(lex, XSDDatatype.XSDduration); return NodeValue.makeNodeDuration(d3, n); @@ -215,6 +161,7 @@ public class NodeValueOps throw new ExprEvalTypeException("Operator '-' : Undefined subtraction: " + nv1 + " and " + nv2); } + /** Multiple two {@link NodeValue NodeValues}, with all the extra datatypes and extensions supported. */ public static NodeValue multiplicationNV(NodeValue nv1, NodeValue nv2) { ValueSpace vs1 = nv1.getValueSpace(); ValueSpace vs2 = nv2.getValueSpace(); @@ -230,12 +177,13 @@ public class NodeValueOps throw new ExprEvalTypeException("Operator '*': only dayTime duration. Got: " + nv1); BigDecimal dec = nv2.getDecimal(); Duration r = dur.multiply(dec); - Node n = NodeFactoryExtra.createLiteralNode(r.toString(), null, dtXSDdayTimeDuration); + Node n = NodeFactory.createLiteral(r.toString(), XSDDatatype.XSDduration); return NodeValue.makeNodeDuration(r, n); } throw new ExprEvalTypeException("Operator '*' : Undefined multiply: " + nv1 + " and " + nv2); } + /** Divide two {@link NodeValue NodeValues}, with all the extra datatypes and extensions supported. */ public static NodeValue divisionNV(NodeValue nv1, NodeValue nv2) { ValueSpace vs1 = nv1.getValueSpace(); ValueSpace vs2 = nv2.getValueSpace(); @@ -243,9 +191,64 @@ public class NodeValueOps if ( vs1.equals(VSPACE_NUM) && vs2.equals(VSPACE_NUM) ) return XSDFuncOp.numDivide(nv1, nv2); + // Duration divided by number + if ( vs1.equals(VSPACE_DURATION) && vs2.equals(VSPACE_NUM) ) { + Duration dur = nv1.getDuration(); + // Multiply by 1/number. + BigDecimal dec = nv2.getDecimal(); + if ( dec.equals(BigDecimal.ZERO) ) + throw new ExprEvalTypeException("Divide by zero in duration division"); + + BigDecimal dec1 = BigDecimal.ONE.divide(dec); + Duration r = dur.multiply(dec1); + // Should normalize but not Duration.normalizeWith for a general duration. + // DT or YM specific normalization could be done. e.g. days can go over 31. + Node n = NodeFactory.createLiteral(r.toString(), XSDDatatype.XSDduration); + return NodeValue.makeNodeDuration(r, n); + } + + // Duration divided by duration + if ( vs1.equals(VSPACE_DURATION) && vs2.equals(VSPACE_DURATION) ) { + // Ratio as a BigDecimal + Duration dur1 = nv1.getDuration(); + Duration dur2 = nv2.getDuration(); + if ( XSDFuncOp.isDayTime(dur1) && XSDFuncOp.isDayTime(dur2) ) { + // In seconds. Ignores fractional seconds. + double x1 = durationDayTimeAsSeconds(dur1); + double x2 = durationDayTimeAsSeconds(dur2); + if ( x2 == 0 ) + throw new ExprEvalTypeException("Divide by zero duration in xsd:dayTimeDuration division"); + return NodeValue.makeDecimal(x1/x2); + } + if ( XSDFuncOp.isYearMonth(dur1) && XSDFuncOp.isYearMonth(dur2) ) { + // In months + double x1 = durationYearMonthAsMonths(dur1); + double x2 = durationYearMonthAsMonths(dur2); + if ( x2 == 0 ) + throw new ExprEvalTypeException("Divide by zero duration in xsd:YearMonthDuration division"); + return NodeValue.makeDecimal(x1/x2); + } + throw new ExprEvalTypeException("Durations not both day-time nor year-month: " + nv1 + " and " + nv2); + } + throw new ExprEvalTypeException("Operator '/' : Undefined division: " + nv1 + " and " + nv2); } + private static double durationYearMonthAsMonths(Duration dur) { + return 12*dur.getYears() + dur.getMonths(); + } + + private static double durationDayTimeAsSeconds(Duration dur) { + double x = dur.getDays(); + x = x * 24; + x = x + dur.getHours(); + x = x * 60; + x = x + dur.getMinutes(); + x = x * 60; + x = x + dur.getSeconds(); + return x; + } + private static boolean isDT(ValueSpace vs) { switch (vs) { case VSPACE_DATETIME: @@ -256,9 +259,9 @@ public class NodeValueOps // case VSPACE_G_MONTHDAY: // case VSPACE_G_MONTH: // case VSPACE_G_DAY: - return true ; + return true; default: - return false ; + return false; } } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java index d74d9f9d27..76b9b9347b 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java @@ -20,124 +20,252 @@ package org.apache.jena.sparql.expr; import static org.junit.Assert.assertEquals; -import org.apache.jena.atlas.logging.Log; import org.apache.jena.sparql.expr.nodevalue.NodeValueOps; import org.junit.Test; -public class TestNodeValueOps -{ +public class TestNodeValueOps { // ** Addition // Numerics - @Test public void nv_add_1() { testAdd("12", "13", "'25'^^xsd:integer" ); } - @Test public void nv_add_2() { testAdd("'12'^^xsd:decimal", "13", "'25.0'^^xsd:decimal" ); } - @Test public void nv_add_3() { testAdd("'12.0'^^xsd:decimal", "13", "'25.0'^^xsd:decimal" ); } - @Test public void nv_add_4() { testAdd("12e0", "13", "25.0e0" ); } + @Test + public void nv_add_1() { + testAdd("12", "13", "'25'^^xsd:integer"); + } + + @Test + public void nv_add_2() { + testAdd("'12'^^xsd:decimal", "13", "'25.0'^^xsd:decimal"); + } + + @Test + public void nv_add_3() { + testAdd("'12.0'^^xsd:decimal", "13", "'25.0'^^xsd:decimal"); + } + + @Test + public void nv_add_4() { + testAdd("12e0", "13", "25.0e0"); + } // Strings - @Test public void nv_add_10() { testAdd("'12'", "'13'", "'1213'" ); } + @Test + public void nv_add_10() { + testAdd("'12'", "'13'", "'1213'"); + } - //Durations (need to test the wiring, not whether the calculation is right) - @Test public void nv_add_20() { testAdd("'PT1H'^^xsd:duration", "'PT1H'^^xsd:duration", "'PT2H'^^xsd:duration" ); } + // Durations (need to test the wiring, not whether the calculation is right) + @Test + public void nv_add_20() { + testAdd("'PT1H'^^xsd:duration", "'PT1H'^^xsd:duration", "'PT2H'^^xsd:duration"); + } - @Test public void nv_add_21() { testAdd("'PT1H'^^xsd:dayTimeDuration", "'PT1H'^^xsd:dayTimeDuration", "'PT2H'^^xsd:dayTimeDuration" ); } + @Test + public void nv_add_21() { + testAdd("'PT1H'^^xsd:dayTimeDuration", "'PT1H'^^xsd:dayTimeDuration", "'PT2H'^^xsd:dayTimeDuration"); + } // Outside the XSD spec. - //@Test public void nv_add_22() { testAdd("'P1Y'^^xsd:yearMonthDuration", "'PT4H'^^xsd:dayTimeDuration", "'P1YT4H'^^xsd:duration" ); } - @Test public void nv_add_22() { - try { - testAdd("'P1Y'^^xsd:yearMonthDuration", "'PT4H'^^xsd:dayTimeDuration", "'P1YT4H'^^xsd:duration" ); - } catch (NullPointerException ex) { - if ( isProbablyIBMJVM() ) - // IBM JDK causes NPE on this one. - // IllegalStateException is acceptable; NullPointerException is not. - Log.warn(this, "TestNodeValueOps.nv_add_22 - IBM JVM - reported issue in the support for xsd:xsd:yearMonthDuration/xsd:dayTimeDuration"); - else - throw ex; - } - catch (IllegalStateException ex) {} - } - - private static boolean isProbablyIBMJVM() - { - return System.getProperty("java.vm.name", "").contains("IBM"); + @Test + public void nv_add_22() { + testAdd("'P1Y'^^xsd:yearMonthDuration", "'PT4H'^^xsd:dayTimeDuration", "'P1YT4H'^^xsd:duration"); } // Date/time + duration - @Test public void nv_add_23() { testAdd("'2000-01-01'^^xsd:date", "'P1Y'^^xsd:duration", "'2001-01-01'^^xsd:date"); } - @Test public void nv_add_24() { testAdd("'2000-01-01T00:00:00Z'^^xsd:dateTime", - "'P1Y1M'^^xsd:yearMonthDuration", - "'2001-02-01T00:00:00Z'^^xsd:dateTime"); } - @Test public void nv_add_25() { testAdd("'2000-01-01T00:00:00Z'^^xsd:dateTime", - "'P1Y1M1DT1H1M1.1S'^^xsd:duration", - "'2001-02-02T01:01:01.1Z'^^xsd:dateTime"); } - @Test public void nv_add_26() { testAdd("'00:00:00'^^xsd:time", - "'PT1H2M3.4S'^^xsd:duration", - "'01:02:03.4'^^xsd:time"); } + @Test + public void nv_add_23() { + testAdd("'2000-01-01'^^xsd:date", "'P1Y'^^xsd:duration", "'2001-01-01'^^xsd:date"); + } + + @Test + public void nv_add_24() { + testAdd("'2000-01-01T00:00:00Z'^^xsd:dateTime", "'P1Y1M'^^xsd:yearMonthDuration", "'2001-02-01T00:00:00Z'^^xsd:dateTime"); + } + + @Test + public void nv_add_25() { + testAdd("'2000-01-01T00:00:00Z'^^xsd:dateTime", "'P1Y1M1DT1H1M1.1S'^^xsd:duration", "'2001-02-02T01:01:01.1Z'^^xsd:dateTime"); + } + + @Test + public void nv_add_26() { + testAdd("'00:00:00'^^xsd:time", "'PT1H2M3.4S'^^xsd:duration", "'01:02:03.4'^^xsd:time"); + } // Bad mixes - @Test(expected=ExprEvalException.class) - public void nv_add_50() { testAdd("'12'", "13"); } + @Test(expected = ExprEvalException.class) + public void nv_add_50() { + testAdd("'12'", "13"); + } - @Test(expected=ExprEvalException.class) - public void nv_add_51() { testAdd("'12'", "'PT1H'^^xsd:duration"); } + @Test(expected = ExprEvalException.class) + public void nv_add_51() { + testAdd("'12'", "'PT1H'^^xsd:duration"); + } - @Test(expected=ExprEvalException.class) - public void nv_add_52() { testAdd("'2012-04-05'^^xsd:date", "'2012-04-05'^^xsd:date"); } + @Test(expected = ExprEvalException.class) + public void nv_add_52() { + testAdd("'2012-04-05'^^xsd:date", "'2012-04-05'^^xsd:date"); + } // ** Subtraction // Numerics - @Test public void nv_sub_1() { testSub("12", "13", "-1" ); } - @Test public void nv_sub_2() { testSub("12", "13.0", "-1.0" ); } - @Test public void nv_sub_3() { testSub("12e0", "13.0", "-1.0e0" ); } + @Test + public void nv_sub_1() { + testSub("12", "13", "-1"); + } + + @Test + public void nv_sub_2() { + testSub("12", "13.0", "-1.0"); + } + + @Test + public void nv_sub_3() { + testSub("12e0", "13.0", "-1.0e0"); + } // Durations - //Durations (need to test the wiring, not whether the calculation is right) - @Test public void nv_sub_20() { testSub("'PT2H'^^xsd:duration", "'PT1H'^^xsd:duration", "'PT1H'^^xsd:duration" ); } - @Test public void nv_sub_21() { testSub("'PT2H'^^xsd:dayTimeDuration", "'PT1H'^^xsd:dayTimeDuration", "'PT1H'^^xsd:dayTimeDuration" ); } - - //@Test public void nv_sub_22() { testSub("'P2Y'^^xsd:yearMonthDuration", "'P1Y'^^xsd:yearMonthDuration", "'P1Y'^^xsd:yearMonthDuration" ); } - @Test public void nv_sub_22() { - try { - testSub("'P2Y'^^xsd:yearMonthDuration", "'P1Y'^^xsd:yearMonthDuration", "'P1Y'^^xsd:yearMonthDuration" ); - } catch (NullPointerException ex) { - if ( isProbablyIBMJVM() ) - // IBM JDK causes NPE on this one. - Log.warn(this, "TestNodeValueOps.nv_sub_22 - IBM JVM - reported issue in the support for xsd:xsd:yearMonthDuration/xsd:dayTimeDuration"); - else - throw ex; - } - catch (IllegalStateException ex) {} - } - - @Test public void nv_sub_23() { testSub("'P3D'^^xsd:dayTimeDuration", "'PT4H'^^xsd:dayTimeDuration", "'P2DT20H'^^xsd:dayTimeDuration" ); } + @Test + public void nv_sub_20() { + testSub("'PT2H'^^xsd:duration", "'PT1H'^^xsd:duration", "'PT1H'^^xsd:duration"); + } + + @Test + public void nv_sub_21() { + testSub("'PT2H'^^xsd:dayTimeDuration", "'PT1H'^^xsd:dayTimeDuration", "'PT1H'^^xsd:dayTimeDuration"); + } + + @Test + public void nv_sub_22() { + testSub("'P2Y'^^xsd:yearMonthDuration", "'P1Y'^^xsd:yearMonthDuration", "'P1Y'^^xsd:yearMonthDuration"); + } + + @Test + public void nv_sub_23() { + testSub("'P3D'^^xsd:dayTimeDuration", "'PT4H'^^xsd:dayTimeDuration", "'P2DT20H'^^xsd:dayTimeDuration"); + } // Date/time - duration - @Test public void nv_sub_30() { testSub("'2000-01-01'^^xsd:date", "'P1Y'^^xsd:duration", "'1999-01-01'^^xsd:date"); } - @Test public void nv_sub_31() { testSub("'2000-01-01T00:00:00Z'^^xsd:dateTime", - "'P1Y1M'^^xsd:yearMonthDuration", - "'1998-12-01T00:00:00Z'^^xsd:dateTime"); } - @Test public void nv_sub_32() { testSub("'2000-01-01T00:00:00Z'^^xsd:dateTime", - "'P1Y1M1DT1H1M1.1S'^^xsd:duration", - "'1998-11-29T22:58:58.9Z'^^xsd:dateTime"); } - - @Test public void nv_sub_33() { testSub("'10:11:12'^^xsd:time", - "'PT1H2M3.4S'^^xsd:duration", - "'09:09:08.6'^^xsd:time"); } + @Test + public void nv_sub_30() { + testSub("'2000-01-01'^^xsd:date", "'P1Y'^^xsd:duration", "'1999-01-01'^^xsd:date"); + } + + @Test + public void nv_sub_31() { + testSub("'2000-01-01T00:00:00Z'^^xsd:dateTime", "'P1Y1M'^^xsd:yearMonthDuration", "'1998-12-01T00:00:00Z'^^xsd:dateTime"); + } + + @Test + public void nv_sub_32() { + testSub("'2000-01-01T00:00:00Z'^^xsd:dateTime", "'P1Y1M1DT1H1M1.1S'^^xsd:duration", "'1998-11-29T22:58:58.9Z'^^xsd:dateTime"); + } + + @Test + public void nv_sub_33() { + testSub("'10:11:12'^^xsd:time", "'PT1H2M3.4S'^^xsd:duration", "'09:09:08.6'^^xsd:time"); + } // Date/time - date/time - // Bad - @Test(expected=ExprEvalException.class) - public void nv_sub_50() { testSub("'12'", "'13'" ); } + @Test(expected = ExprEvalException.class) + public void nv_sub_50() { + testSub("'12'", "'13'"); + } // ** Multiplication - @Test public void nv_mult_1() { testMult("12", "13", "156" ); } - @Test public void nv_mult_2() { testMult("-12", "13.0", "-156.0" ); } - @Test public void nv_mult_3() { testMult("'PT1H2M'^^xsd:duration", "2", "'PT2H4M'^^xsd:dayTimeDuration"); } + @Test + public void nv_mult_1() { + testMult("12", "13", "156"); + } + + @Test + public void nv_mult_2() { + testMult("-12", "13.0", "-156.0"); + } + + @Test + public void nv_mult_3() { + testMult("'PT1H2M'^^xsd:duration", "2", "'PT2H4M'^^xsd:duration"); + } // ** Division - @Test public void nv_div_1() { testDiv("12", "2", "6.0" ); } - @Test public void nv_div_2() { testDiv("12", "2e0", "6.0e0" ); } + @Test + public void nv_div_num_1() { + testDiv("12", "2", "6.0"); + } + + @Test + public void nv_div_num_2() { + testDiv("12", "2e0", "6.0e0"); + } + + @Test + public void nv_div_dur_3() { + testDiv("'PT24H20M'^^xsd:duration", "2", "'PT12H10M'^^xsd:duration"); + } + + @Test + public void nv_div_dur_4() { + testDiv("'PT24H20M'^^xsd:dayTimeDuration", "2", "'PT12H10M'^^xsd:duration"); + } + + // Note - not normalized. + @Test + public void nv_div_dur_5() { + testDiv("'PT24H20M'^^xsd:dayTimeDuration", "0.1", "'PT240H200M'^^xsd:duration"); + } + + @Test + public void nv_div_dur_6() { + testDiv("'P2Y8M'^^xsd:duration", "2", "'P1Y4M'^^xsd:duration"); + } + + @Test + public void nv_div_dur_7() { + testDiv("'P2Y8M'^^xsd:yearMonthDuration", "2", "'P1Y4M'^^xsd:duration"); + } + + // Note - not normalized. + @Test + public void nv_div_dur_8() { + testDiv("'P2Y8M'^^xsd:yearMonthDuration", "0.1", "'P20Y80M'^^xsd:duration"); + } + + @Test(expected = ExprEvalException.class) + public void nv_div_dur_bad_1() { + // Year-month divided by day-time + testDiv("'P2Y8M'^^xsd:yearMonthDuration", "'PT12H10M'^^xsd:duration"); + } + + @Test(expected = ExprEvalException.class) + public void nv_div_dur_bad_2() { + // day-time divided by year-month. + testDiv("'PT12H10M'^^xsd:duration", "'P2Y8M'^^xsd:duration"); + } + + @Test(expected = ExprEvalException.class) + public void nv_div_dur_bad_3() { + // day-time divided by year-month. + testDiv("'PT12H10M'^^xsd:duration", "0"); + } + + @Test(expected = ExprEvalException.class) + public void nv_div_dur_bad_4() { + // day-time divided by year-month. + testDiv("'P1Y'^^xsd:duration", "0"); + } + + @Test(expected = ExprEvalException.class) + public void nv_div_dur_bad_5() { + // day-time divided by zero interval. + testDiv("'PT1H'^^xsd:duration", "'PT0S'^^xsd:duration"); + } + + @Test(expected = ExprEvalException.class) + public void nv_div_dur_bad_6() { + // year-month divided by zero interval. + testDiv("'P1Y'^^xsd:duration", "'P0Y'^^xsd:duration"); + } // == Workers
