From: Nick Burch Date: Mon, 4 Feb 2013 22:01:55 +0000 (+0000) Subject: EDate function implementation from Detlef Brendle from bug #54508 X-Git-Tag: 3.10-beta1~57 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3460c45bc3281fa76b26fe32193c85d41d5bbf5e;p=poi.git EDate function implementation from Detlef Brendle from bug #54508 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1442392 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java b/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java index a9343e67a3..28215641fd 100644 --- a/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java +++ b/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java @@ -15,6 +15,7 @@ import org.apache.poi.ss.formula.eval.NotImplementedException; import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.function.FunctionMetadata; import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; +import org.apache.poi.ss.formula.functions.EDate; import org.apache.poi.ss.formula.functions.FreeRefFunction; import org.apache.poi.ss.formula.functions.Sumifs; import org.apache.poi.ss.formula.udf.UDFFinder; @@ -99,7 +100,7 @@ public final class AnalysisToolPak implements UDFFinder { r(m, "DOLLARDE", null); r(m, "DOLLARFR", null); r(m, "DURATION", null); - r(m, "EDATE", null); + r(m, "EDATE", EDate.instance); r(m, "EFFECT", null); r(m, "EOMONTH", null); r(m, "ERF", null); diff --git a/src/java/org/apache/poi/ss/formula/functions/EDate.java b/src/java/org/apache/poi/ss/formula/functions/EDate.java new file mode 100644 index 0000000000..fbc08c068f --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/functions/EDate.java @@ -0,0 +1,43 @@ +package org.apache.poi.ss.formula.functions; + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.*; +import org.apache.poi.ss.usermodel.DateUtil; + +import java.util.Calendar; +import java.util.Date; + +public class EDate implements FreeRefFunction { + public static final FreeRefFunction instance = new EDate(); + + @Override + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length != 2) { + return ErrorEval.VALUE_INVALID; + } + try { + double startDateAsNumber = getValue(args[0]); + NumberEval offsetInYearsValue = (NumberEval) args[1]; + int offsetInMonthAsNumber = (int) offsetInYearsValue.getNumberValue(); + + Date startDate = DateUtil.getJavaDate(startDateAsNumber); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(startDate); + calendar.add(Calendar.MONTH, offsetInMonthAsNumber); + return new NumberEval(DateUtil.getExcelDate(calendar.getTime())); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + } + + private double getValue(ValueEval arg) throws EvaluationException { + if (arg instanceof NumberEval) { + return ((NumberEval) arg).getNumberValue(); + } + if (arg instanceof RefEval) { + ValueEval innerValueEval = ((RefEval) arg).getInnerValueEval(); + return ((NumberEval) innerValueEval).getNumberValue(); + } + throw new EvaluationException(ErrorEval.REF_INVALID); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestEDate.java b/src/testcases/org/apache/poi/ss/formula/functions/TestEDate.java new file mode 100644 index 0000000000..cf1943806d --- /dev/null +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestEDate.java @@ -0,0 +1,51 @@ +package org.apache.poi.ss.formula.functions; + +import junit.framework.TestCase; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.ErrorConstants; + +import java.util.Calendar; +import java.util.Date; + +public class TestEDate extends TestCase{ + + public void testEDateProperValues() { + EDate eDate = new EDate(); + NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000), new NumberEval(0)}, null); + assertEquals(1000d, result.getNumberValue()); + } + + public void testEDateInvalidValues() { + EDate eDate = new EDate(); + ErrorEval result = (ErrorEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000)}, null); + assertEquals(ErrorConstants.ERROR_VALUE, result.getErrorCode()); + } + + public void testEDateIncrease() { + EDate eDate = new EDate(); + Date startDate = new Date(); + int offset = 2; + NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null); + Date resultDate = DateUtil.getJavaDate(result.getNumberValue()); + Calendar instance = Calendar.getInstance(); + instance.setTime(startDate); + instance.add(Calendar.MONTH, offset); + assertEquals(resultDate, instance.getTime()); + + } + + public void testEDateDecrease() { + EDate eDate = new EDate(); + Date startDate = new Date(); + int offset = -2; + NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null); + Date resultDate = DateUtil.getJavaDate(result.getNumberValue()); + Calendar instance = Calendar.getInstance(); + instance.setTime(startDate); + instance.add(Calendar.MONTH, offset); + assertEquals(resultDate, instance.getTime()); + } +}