From: PJ Fanning Date: Fri, 11 Feb 2022 23:17:48 +0000 (+0000) Subject: add workday tests X-Git-Tag: REL_5_2_1~83 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d9902ee89853ffb6c410bf188eb6e8fd53a7d179;p=poi.git add workday tests git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1897984 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java index c9cdcb2853..67b20b3954 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java @@ -73,13 +73,13 @@ public class WorkdayCalculator { weekendTypeMap.put(5, wedsThursWeekend); weekendTypeMap.put(6, thursFriWeekend); weekendTypeMap.put(7, friSatWeekend); - weekendTypeMap.put(11, monWeekend); - weekendTypeMap.put(12, tuesWeekend); - weekendTypeMap.put(13, wedsWeekend); - weekendTypeMap.put(14, thursWeekend); - weekendTypeMap.put(15, friWeekend); - weekendTypeMap.put(16, satWeekend); - weekendTypeMap.put(17, sunWeekend); + weekendTypeMap.put(11, sunWeekend); + weekendTypeMap.put(12, monWeekend); + weekendTypeMap.put(13, tuesWeekend); + weekendTypeMap.put(14, wedsWeekend); + weekendTypeMap.put(15, thursWeekend); + weekendTypeMap.put(16, friWeekend); + weekendTypeMap.put(17, satWeekend); } /** diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java index 2e3b16b940..7067ccb266 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java @@ -18,6 +18,7 @@ package org.apache.poi.ss.formula.atp; import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.BlankEval; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.NumberEval; @@ -69,7 +70,9 @@ final class WorkdayIntlFunction implements FreeRefFunction { start = this.evaluator.evaluateDateArg(args[0], srcCellRow, srcCellCol); days = (int) Math.floor(this.evaluator.evaluateNumberArg(args[1], srcCellRow, srcCellCol)); if (args.length >= 3) { - weekendType = (int) this.evaluator.evaluateNumberArg(args[2], srcCellRow, srcCellCol); + if (args[2] != BlankEval.instance) { + weekendType = (int) this.evaluator.evaluateNumberArg(args[2], srcCellRow, srcCellCol); + } if (!WorkdayCalculator.instance.getValidWeekendTypes().contains(weekendType)) { return ErrorEval.NUM_ERROR; } diff --git a/poi/src/test/java/org/apache/poi/ss/formula/atp/TestWorkdayIntlFunction.java b/poi/src/test/java/org/apache/poi/ss/formula/atp/TestWorkdayIntlFunction.java new file mode 100644 index 0000000000..18e2c240a2 --- /dev/null +++ b/poi/src/test/java/org/apache/poi/ss/formula/atp/TestWorkdayIntlFunction.java @@ -0,0 +1,247 @@ +/* ==================================================================== + 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.poi.ss.formula.atp; + + +import org.apache.poi.ss.formula.OperationEvaluationContext; +import org.apache.poi.ss.formula.TwoDEval; +import org.apache.poi.ss.formula.eval.AreaEval; +import org.apache.poi.ss.formula.eval.AreaEvalBase; +import org.apache.poi.ss.formula.eval.BlankEval; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.util.LocaleUtil; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TestWorkdayIntlFunction { + + private static final String STARTING_DATE = "2008/10/01"; + private static final String FIRST_HOLIDAY = "2008/11/26"; + private static final String SECOND_HOLIDAY = "2008/12/04"; + private static final String THIRD_HOLIDAY = "2009/01/21"; + private static final String RETROATIVE_HOLIDAY = "2008/09/29"; + + private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null); + + @Test + void testFailWhenNoArguments() { + ValueEval[] ve = new ValueEval[0]; + assertEquals(VALUE_INVALID, WorkdayIntlFunction.instance.evaluate(ve, null)); + } + + @Test + void testFailWhenLessThan2Arguments() { + ValueEval[] ve = new ValueEval[1]; + assertEquals(VALUE_INVALID, WorkdayIntlFunction.instance.evaluate(ve, null)); + } + + @Test + void testFailWhenMoreThan4Arguments() { + ValueEval[] ve = new ValueEval[5]; + assertEquals(VALUE_INVALID, WorkdayIntlFunction.instance.evaluate(ve, null)); + } + + @Test + void testFailWhenArgumentsAreNotDatesNorNumbers() { + ValueEval[] ve = {new StringEval("Potato"), new StringEval("Cucumber")}; + assertEquals(VALUE_INVALID, WorkdayIntlFunction.instance.evaluate(ve, EC)); + } + + @Test + void testReturnWorkdays() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 3, 30); + Date expDate = expCal.getTime(); + ValueEval[] ve = {new StringEval(STARTING_DATE), new NumberEval(151)}; + Date actDate = DateUtil.getJavaDate(((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue()); + assertEquals(expDate, actDate); + } + + @Test + void testReturnWorkdaysSpanningAWeekendSubtractingDays() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 8, 27); + Date expDate = expCal.getTime(); + + ValueEval[] ve = {new StringEval("2013/09/30"), new NumberEval(-1)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + assertEquals(41544.0, numberValue, 0); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testReturnWorkdaysSpanningAWeekendAddingDays() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 8, 30); + Date expDate = expCal.getTime(); + + ValueEval[] ve = {new StringEval("2013/09/27"), new NumberEval(1)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + assertEquals(41547.0, numberValue, 0); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testReturnWorkdaysWhenStartIsWeekendAddingDays() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 9, 7); + Date expDate = expCal.getTime(); + + ValueEval[] ve = {new StringEval("2013/10/06"), new NumberEval(1)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + assertEquals(41554.0, numberValue, 0); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testReturnWorkdaysWhenStartIsWeekendSubtractingDays() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 9, 4); + Date expDate = expCal.getTime(); + + ValueEval[] ve = {new StringEval("2013/10/06"), new NumberEval(-1)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + assertEquals(41551.0, numberValue, 0); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testReturnWorkdaysWithDaysTruncated() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 3, 30); + Date expDate = expCal.getTime(); + + ValueEval[] ve = {new StringEval(STARTING_DATE), new NumberEval(151.99999)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testReturnRetroativeWorkday() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2008, 8, 23); + Date expDate = expCal.getTime(); + + ValueEval[] ve = {new StringEval(STARTING_DATE), new NumberEval(-5), + BlankEval.instance, new StringEval(RETROATIVE_HOLIDAY)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testReturnNetworkdaysWithManyHolidays() { + Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 4, 5); + Date expDate = expCal.getTime(); + + ValueEval[] ve = { + new StringEval(STARTING_DATE), new NumberEval(151), BlankEval.instance, + new MockAreaEval(FIRST_HOLIDAY, SECOND_HOLIDAY, THIRD_HOLIDAY)}; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + + Date actDate = DateUtil.getJavaDate(numberValue); + assertEquals(expDate, actDate); + } + + @Test + void testMicrosoftExample1() { + final String testDate = "2012-01-01"; + ValueEval[] ve = { + new StringEval(testDate), new NumberEval(30), new NumberEval(0) + }; + assertEquals(ErrorEval.NUM_ERROR, WorkdayIntlFunction.instance.evaluate(ve, EC)); + } + + @Test + void testMicrosoftExample2() { + final String testDate = "2012-01-01"; + ValueEval[] ve = { + new StringEval(testDate), new NumberEval(90), new NumberEval(11) + }; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + assertEquals(41013.0, numberValue); + } + + @Test + void testMicrosoftExample3() { + final String testDate = "2012-01-01"; + ValueEval[] ve = { + new StringEval(testDate), new NumberEval(30), new NumberEval(17) + }; + double numberValue = ((NumberEval) WorkdayIntlFunction.instance.evaluate(ve, EC)).getNumberValue(); + assertEquals(40944.0, numberValue); + } + + private class MockAreaEval extends AreaEvalBase { + + private List holidays; + + public MockAreaEval(String... holidays) { + this(0, 0, 0, holidays.length - 1); + this.holidays = new ArrayList<>(); + for (String holiday : holidays) { + this.holidays.add(new StringEval(holiday)); + } + } + + protected MockAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn) { + super(firstRow, firstColumn, lastRow, lastColumn); + } + + @Override + public ValueEval getRelativeValue(int sheetIndex, int relativeRowIndex, int relativeColumnIndex) { + return this.holidays.get(relativeColumnIndex); + } + @Override + public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) { + return getRelativeValue(-1, relativeRowIndex, relativeColumnIndex); + } + + @Override + public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) { + return null; + } + + @Override + public TwoDEval getColumn(int columnIndex) { + return null; + } + + @Override + public TwoDEval getRow(int rowIndex) { + return null; + } + + } +}