Author: cedricwalter
Date: Thu Oct 10 21:54:52 2013
New Revision: 1531124

URL: http://svn.apache.org/r1531124
Log:
Bug 55649: WORKDAY Function returns incorrect date when spanning a weekend, or 
the start date is a weekend

Modified:
    poi/trunk/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java
    
poi/trunk/src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java

Modified: 
poi/trunk/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java?rev=1531124&r1=1531123&r2=1531124&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java Thu 
Oct 10 21:54:52 2013
@@ -61,24 +61,24 @@ public class WorkdayCalculator {
      * @param holidays an array of holidays.
      * @return date past x workdays.
      */
-    public Date calculateWorkdays(double start, int workdays, double[] 
holidays) {
-        Date startDate = DateUtil.getJavaDate(start);
-        Calendar endDate = Calendar.getInstance();
-        endDate.setTime(startDate);
-        endDate.add(Calendar.DAY_OF_YEAR, workdays);
-        int skippedDays = 0;
-        do {
-            double end = DateUtil.getExcelDate(endDate.getTime());
-            int saturdaysPast = this.pastDaysOfWeek(start, end, 
Calendar.SATURDAY);
-            int sundaysPast = this.pastDaysOfWeek(start, end, Calendar.SUNDAY);
-            int nonWeekendHolidays = this.calculateNonWeekendHolidays(start, 
end, holidays);
-            skippedDays = saturdaysPast + sundaysPast + nonWeekendHolidays;
-            endDate.add(Calendar.DAY_OF_YEAR, skippedDays);
-            start = end + isNonWorkday(end, holidays);
-        } while (skippedDays != 0);
-        return endDate.getTime();
-    }
-
+       public Date calculateWorkdays(double start, int workdays, double[] 
holidays) {
+               Date startDate = DateUtil.getJavaDate(start);
+               int direction = workdays < 0 ? -1 : 1;
+               Calendar endDate = Calendar.getInstance();
+               endDate.setTime(startDate);
+               double excelEndDate = DateUtil.getExcelDate(endDate.getTime());
+               while (workdays != 0) {
+                       endDate.add(Calendar.DAY_OF_YEAR, direction);
+                       excelEndDate += direction;
+                       if (endDate.get(Calendar.DAY_OF_WEEK) != 
Calendar.SATURDAY
+                                       && endDate.get(Calendar.DAY_OF_WEEK) != 
Calendar.SUNDAY
+                                       && !isHoliday(excelEndDate,     
holidays)) {
+                               workdays -= direction;
+                       }
+               }
+               return endDate.getTime();
+       }
+    
     /**
      * Calculates how many days of week past between a start and an end date.
      * 

Modified: 
poi/trunk/src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java?rev=1531124&r1=1531123&r2=1531124&view=diff
==============================================================================
--- 
poi/trunk/src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java 
(original)
+++ 
poi/trunk/src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java 
Thu Oct 10 21:54:52 2013
@@ -85,6 +85,46 @@ public class TestWorkdayFunction extends
                 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() {
         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()));



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to