Bug 55649: WORKDAY Function returns incorrect date when spanning a weekend, or the start date is a weekend

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1531124 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Cédric Walter 2013-10-10 21:54:52 +00:00
parent f15a35ec45
commit 61f1130e38
2 changed files with 58 additions and 18 deletions

View File

@ -61,24 +61,24 @@ public class WorkdayCalculator {
* @param holidays an array of holidays. * @param holidays an array of holidays.
* @return date past x workdays. * @return date past x workdays.
*/ */
public Date calculateWorkdays(double start, int workdays, double[] holidays) { public Date calculateWorkdays(double start, int workdays, double[] holidays) {
Date startDate = DateUtil.getJavaDate(start); Date startDate = DateUtil.getJavaDate(start);
Calendar endDate = Calendar.getInstance(); int direction = workdays < 0 ? -1 : 1;
endDate.setTime(startDate); Calendar endDate = Calendar.getInstance();
endDate.add(Calendar.DAY_OF_YEAR, workdays); endDate.setTime(startDate);
int skippedDays = 0; double excelEndDate = DateUtil.getExcelDate(endDate.getTime());
do { while (workdays != 0) {
double end = DateUtil.getExcelDate(endDate.getTime()); endDate.add(Calendar.DAY_OF_YEAR, direction);
int saturdaysPast = this.pastDaysOfWeek(start, end, Calendar.SATURDAY); excelEndDate += direction;
int sundaysPast = this.pastDaysOfWeek(start, end, Calendar.SUNDAY); if (endDate.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY
int nonWeekendHolidays = this.calculateNonWeekendHolidays(start, end, holidays); && endDate.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY
skippedDays = saturdaysPast + sundaysPast + nonWeekendHolidays; && !isHoliday(excelEndDate, holidays)) {
endDate.add(Calendar.DAY_OF_YEAR, skippedDays); workdays -= direction;
start = end + isNonWorkday(end, holidays); }
} while (skippedDays != 0); }
return endDate.getTime(); return endDate.getTime();
} }
/** /**
* Calculates how many days of week past between a start and an end date. * Calculates how many days of week past between a start and an end date.
* *

View File

@ -85,6 +85,46 @@ public class TestWorkdayFunction extends TestCase {
new StringEval(STARTING_DATE.toString()), new NumberEval(151) }, EC)).getNumberValue())); new StringEval(STARTING_DATE.toString()), new NumberEval(151) }, EC)).getNumberValue()));
} }
public void testReturnWorkdaysSpanningAWeekendSubtractingDays() {
String startDate = "2013/09/30";
int days = -1;
String expectedWorkDay = "2013/09/27";
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(expectedWorkDay, formatter.format(DateUtil.getJavaDate(numberValue)));
}
public void testReturnWorkdaysSpanningAWeekendAddingDays() {
String startDate = "2013/09/27";
int days = 1;
String expectedWorkDay = "2013/09/30";
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(expectedWorkDay, formatter.format(DateUtil.getJavaDate(numberValue)));
}
public void testReturnWorkdaysWhenStartIsWeekendAddingDays() {
String startDate = "2013/10/06";
int days = 1;
String expectedWorkDay = "2013/10/07";
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(expectedWorkDay, formatter.format(DateUtil.getJavaDate(numberValue)));
}
public void testReturnWorkdaysWhenStartIsWeekendSubtractingDays() {
String startDate = "2013/10/06";
int days = -1;
String expectedWorkDay = "2013/10/04";
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(expectedWorkDay, formatter.format(DateUtil.getJavaDate(numberValue)));
}
public void testReturnWorkdaysWithDaysTruncated() { public void testReturnWorkdaysWithDaysTruncated() {
assertEquals(new Date(109, APRIL, 30), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{ assertEquals(new Date(109, APRIL, 30), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
new StringEval(STARTING_DATE.toString()), new NumberEval(151.99999) }, EC)).getNumberValue())); new StringEval(STARTING_DATE.toString()), new NumberEval(151.99999) }, EC)).getNumberValue()));