Repository: jena Updated Branches: refs/heads/master 7f2dfed0a -> edba13136
First implementation of fn:adjust-dateTime-to-timezone. Project: http://git-wip-us.apache.org/repos/asf/jena/repo Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/da73e967 Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/da73e967 Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/da73e967 Branch: refs/heads/master Commit: da73e967b19f00f4d5f8b245079b9894331715db Parents: f2ae5db Author: ales004 <[email protected]> Authored: Sun May 29 19:13:47 2016 +0200 Committer: ales004 <[email protected]> Committed: Sun May 29 19:13:47 2016 +0200 ---------------------------------------------------------------------- .../jena/sparql/expr/nodevalue/XSDFuncOp.java | 61 +++++++++++++++++--- .../jena/sparql/function/StandardFunctions.java | 1 + .../library/FN_AdjustDatetimeToTimezone.java | 55 ++++++++++++++++++ .../apache/jena/sparql/expr/TestFunctions.java | 38 +++++++++++- 4 files changed, 147 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jena/blob/da73e967/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java index 817c20f..8b31d92 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java @@ -34,10 +34,7 @@ import static org.apache.jena.sparql.expr.nodevalue.NumericType.OP_INTEGER ; import java.math.BigDecimal ; import java.math.BigInteger ; import java.text.Normalizer; -import java.util.ArrayList; -import java.util.HashSet ; -import java.util.List ; -import java.util.Set ; +import java.util.*; import java.util.regex.Matcher ; import java.util.regex.Pattern ; @@ -1426,10 +1423,9 @@ public class XSDFuncOp return NodeValue.makeString(dts.timezone) ; } - public static NodeValue dtGetTimezone(NodeValue nv) { - DateTimeStruct dts = parseAnyDT(nv) ; + private static NodeValue fromTimezoneToDuration(DateTimeStruct dts){ if ( dts == null || dts.timezone == null ) - throw new ExprEvalException("Not a datatype with a timezone: " + nv) ; + return null; if ( "".equals(dts.timezone) ) return null ; if ( "Z".equals(dts.timezone) ) { @@ -1460,6 +1456,13 @@ public class XSDFuncOp return NodeValue.makeNode(sb.toString(), null, XSDDatatype.XSD + "#dayTimeDuration") ; } + public static NodeValue dtGetTimezone(NodeValue nv) { + DateTimeStruct dts = parseAnyDT(nv) ; + if ( dts == null || dts.timezone == null ) + throw new ExprEvalException("Not a datatype with a timezone: " + nv) ; + return fromTimezoneToDuration(dts); + } + private static void digitsTwo(String s, int idx, StringBuilder sb, char indicator) { if ( s.charAt(idx) == '0' ) { idx++ ; @@ -1554,4 +1557,48 @@ public class XSDFuncOp // dur = ... return dur ; } + + public static NodeValue adjustDatetimeToTimezone(NodeValue nv1,NodeValue nv2){ + if(nv1 == null) + return null; + + if(!nv1.isDateTime() && !nv1.isDate()){ + throw new ExprEvalException("Not a valid date or datetime:"+nv1); + } + DateTimeStruct dts = parseAnyDT(nv1); + NodeValue inputTimezone = fromTimezoneToDuration(dts); + Boolean hasTz = inputTimezone == null ? false : true; + XMLGregorianCalendar calValue = nv1.getDateTime(); + int inputOffset = 0; + if(hasTz){ + Duration inputDuration = inputTimezone.getDuration(); + inputOffset = inputDuration.getSign()*(inputDuration.getMinutes() + 60*inputDuration.getHours()); + } + + int tzOffset = TimeZone.getDefault().getRawOffset() / (1000*60); + if(nv2 != null){ + if(!nv2.isDuration()) { + String nv2StrValue = nv2.getString(); + if(nv2StrValue.equals("")){ + calValue.setTimezone(DatatypeConstants.FIELD_UNDEFINED); + if(nv1.isDateTime()) + return NodeValue.makeDateTime(calValue); + else + return NodeValue.makeDate(calValue); + } + throw new ExprEvalException("Not a valid duration:" + nv2); + } + Duration tzDuration = nv2.getDuration(); + tzOffset = tzDuration.getSign()*(tzDuration.getMinutes() + 60*tzDuration.getHours()); + } + String tzSign = (tzOffset-inputOffset) > 0 ? "" : "-"; + Duration durToAdd = NodeValue.makeDuration(tzSign+"PT"+java.lang.Math.abs(tzOffset-inputOffset)+"M").getDuration(); + if(hasTz) + calValue.add(durToAdd); + calValue.setTimezone(tzOffset); + if(nv1.isDateTime()) + return NodeValue.makeDateTime(calValue); + else + return NodeValue.makeDate(calValue); + } } http://git-wip-us.apache.org/repos/asf/jena/blob/da73e967/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java index 9594059..e8b014d 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java @@ -164,6 +164,7 @@ public class StandardFunctions // XQ/XP 3. // 9.6.1 fn:adjust-dateTime-to-timezone + add(registry, xfn+"adjust-dateTime-to-timezone", FN_AdjustDatetimeToTimezone.class) ; // 9.6.2 fn:adjust-date-to-timezone // 9.6.3 fn:adjust-time-to-timezone // 9.8.1 fn:format-dateTime http://git-wip-us.apache.org/repos/asf/jena/blob/da73e967/jena-arq/src/main/java/org/apache/jena/sparql/function/library/FN_AdjustDatetimeToTimezone.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/library/FN_AdjustDatetimeToTimezone.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/library/FN_AdjustDatetimeToTimezone.java new file mode 100644 index 0000000..7d480dd --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/library/FN_AdjustDatetimeToTimezone.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jena.sparql.function.library; + +import org.apache.jena.atlas.lib.Lib; +import org.apache.jena.query.QueryBuildException; +import org.apache.jena.sparql.expr.ExprEvalException; +import org.apache.jena.sparql.expr.ExprList; +import org.apache.jena.sparql.expr.NodeValue; +import org.apache.jena.sparql.expr.nodevalue.XSDFuncOp; +import org.apache.jena.sparql.function.FunctionBase; + +import java.util.List; + +public class FN_AdjustDatetimeToTimezone extends FunctionBase { + public FN_AdjustDatetimeToTimezone(){super();} + + @Override + public void checkBuild(String uri, ExprList args) + { + if ( args.size() != 1 && args.size() != 2 ) + throw new QueryBuildException("Function '"+ Lib.className(this)+"' takes one or two arguments") ; + } + @Override + public NodeValue exec(List<NodeValue> args) + { + if ( args.size() != 1 && args.size() != 2 ) + throw new ExprEvalException("FN_StrNormalizeUnicode: Wrong number of arguments: "+args.size()+" : [wanted 1 or 2]") ; + + NodeValue v1 = args.get(0) ; + + if ( args.size() == 2 ) + { + NodeValue v2 = args.get(1) ; + return XSDFuncOp.adjustDatetimeToTimezone(v1, v2) ; + } + + return XSDFuncOp.adjustDatetimeToTimezone(v1, null) ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/da73e967/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions.java ---------------------------------------------------------------------- diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions.java index 589c9c4..3864711 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions.java @@ -348,6 +348,35 @@ public class TestFunctions // counter-intuitive -- would fail if float/double not translated to decimal @Test public void exprRoundHalfEven_08() { test("fn:round-half-to-even('150.015'^^xsd:float, 2)", NodeValue.makeFloat((float)150.01)) ; } + private String getDynamicDurationString(){ + int tzOffset = TimeZone.getDefault().getRawOffset() / (1000*60); + return "PT"+tzOffset+"M"; + } + + @Test public void exprAdjustDatetimeToTz_01(){ + testEqual( + "fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00'^^xsd:dateTime)", + "fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00'^^xsd:dateTime,'"+getDynamicDurationString()+"'^^xsd:dayTimeDuration)"); + } + + @Test public void exprAdjustDatetimeToTz_02(){ + testEqual( + "fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00-07:00'^^xsd:dateTime)", + "fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00-07:00'^^xsd:dateTime,'"+getDynamicDurationString()+"'^^xsd:dayTimeDuration)"); + } + + @Test public void exprAdjustDatetimeToTz_03(){test("fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00'^^xsd:dateTime,'-PT10H'^^xsd:dayTimeDuration)",NodeValue.makeDateTime("2002-03-07T10:00:00-10:00"));} + + @Test public void exprAdjustDatetimeToTz_04(){test("fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00-07:00'^^xsd:dateTime,'-PT10H'^^xsd:dayTimeDuration)",NodeValue.makeDateTime("2002-03-07T07:00:00-10:00"));} + + @Test public void exprAdjustDatetimeToTz_05(){test("fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00-07:00'^^xsd:dateTime,'PT10H'^^xsd:dayTimeDuration)",NodeValue.makeDateTime("2002-03-08T03:00:00+10:00"));} + + @Test public void exprAdjustDatetimeToTz_06(){test("fn:adjust-dateTime-to-timezone('2002-03-07T00:00:00+01:00'^^xsd:dateTime,'-PT8H'^^xsd:dayTimeDuration)",NodeValue.makeDateTime("2002-03-06T15:00:00-08:00"));} + + @Test public void exprAdjustDatetimeToTz_07(){test("fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00'^^xsd:dateTime,'')",NodeValue.makeDateTime("2002-03-07T10:00:00"));} + + @Test public void exprAdjustDatetimeToTz_08(){test("fn:adjust-dateTime-to-timezone('2002-03-07T10:00:00-07:00'^^xsd:dateTime,'')",NodeValue.makeDateTime("2002-03-07T10:00:00"));} + //@Test public void exprStrJoin() { test("fn:string-join('a', 'b')", NodeValue.makeString("ab")) ; } @Test public void exprSameTerm1() { test("sameTerm(1,1)", TRUE) ; } @@ -402,7 +431,14 @@ public class TestFunctions NodeValue r = expr.eval(null, FunctionEnvBase.createTest()) ; assertEquals(result, r) ; } - + + private void testEqual(String exprStr, String exprStrExpected) + { + Expr expr = ExprUtils.parse(exprStrExpected) ; + NodeValue rExpected = expr.eval(null, FunctionEnvBase.createTest()) ; + test(exprStr,rExpected); + } + private void testEvalException(String exprStr) { Expr expr = ExprUtils.parse(exprStr) ;
