You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2021/10/03 13:17:48 UTC

svn commit: r1893852 - in /poi/trunk/poi/src: main/java/org/apache/poi/ss/formula/functions/WeekNum.java test/java/org/apache/poi/ss/formula/functions/TestWeekNumFunc.java test/java/org/apache/poi/ss/formula/functions/TestWeekdayFunc.java

Author: fanningpj
Date: Sun Oct  3 13:17:48 2021
New Revision: 1893852

URL: http://svn.apache.org/viewvc?rev=1893852&view=rev
Log:
[bug-65606] try to fix weeknum function

Modified:
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/WeekNum.java
    poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekNumFunc.java
    poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekdayFunc.java

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/WeekNum.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/WeekNum.java?rev=1893852&r1=1893851&r2=1893852&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/WeekNum.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/WeekNum.java Sun Oct  3 13:17:48 2021
@@ -17,16 +17,17 @@
 
 package org.apache.poi.ss.formula.functions;
 
-import java.util.Calendar;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.temporal.WeekFields;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
 
 import org.apache.poi.ss.formula.OperationEvaluationContext;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.ss.formula.eval.EvaluationException;
-import org.apache.poi.ss.formula.eval.NumberEval;
-import org.apache.poi.ss.formula.eval.OperandResolver;
-import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.eval.*;
 import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.util.LocaleUtil;
 
 /**
  * Implementation for Excel WeekNum() function.
@@ -45,6 +46,8 @@ import org.apache.poi.util.LocaleUtil;
 public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
     public static final FreeRefFunction instance = new WeekNum();
     private static final NumberEval DEFAULT_RETURN_TYPE = new NumberEval(1);
+    private static final HashSet<Integer> VALID_RETURN_TYPES = new HashSet<>(
+            Arrays.asList(1, 2, 11, 12, 13, 14, 15, 16, 17, 21));
 
     @Override
     public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) {
@@ -54,31 +57,60 @@ public class WeekNum extends Fixed2ArgFu
         } catch (EvaluationException e) {
             return ErrorEval.VALUE_INVALID;
         }
-        Calendar serialNumCalendar = LocaleUtil.getLocaleCalendar();
-        serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false));
-
+        LocalDate localDate;
+        try {
+            Date dateToConvert = DateUtil.getJavaDate(serialNum, false);
+            localDate = dateToConvert.toInstant()
+                    .atZone(ZoneId.systemDefault())
+                    .toLocalDate();
+        } catch (Exception e) {
+            return ErrorEval.NUM_ERROR;
+        }
         int returnType;
         try {
             ValueEval ve = OperandResolver.getSingleValue(returnTypeVE, srcRowIndex, srcColumnIndex);
-            returnType = OperandResolver.coerceValueToInt(ve);
+            if (ve instanceof MissingArgEval) {
+                returnType = (int)DEFAULT_RETURN_TYPE.getNumberValue();
+            } else {
+                returnType = OperandResolver.coerceValueToInt(ve);
+            }
         } catch (EvaluationException e) {
             return ErrorEval.NUM_ERROR;
         }
 
-        if (returnType != 1 && returnType != 2) {
+        if (!VALID_RETURN_TYPES.contains(returnType)) {
             return ErrorEval.NUM_ERROR;
         }
 
-        return new NumberEval(this.getWeekNo(serialNumCalendar, returnType));
+        return new NumberEval(this.getWeekNo(localDate, returnType));
     }
 
-    public int getWeekNo(Calendar cal, int weekStartOn) {
-        if (weekStartOn == 1) {
-            cal.setFirstDayOfWeek(Calendar.SUNDAY);
+    private WeekFields SUNDAY_START = WeekFields.of(DayOfWeek.SUNDAY, 1);
+    private WeekFields MONDAY_START = WeekFields.of(DayOfWeek.MONDAY, 1);
+    private WeekFields TUESDAY_START = WeekFields.of(DayOfWeek.TUESDAY, 1);
+    private WeekFields WEDNESDAY_START = WeekFields.of(DayOfWeek.WEDNESDAY, 1);
+    private WeekFields THURSDAY_START = WeekFields.of(DayOfWeek.THURSDAY, 1);
+    private WeekFields FRIDAY_START = WeekFields.of(DayOfWeek.FRIDAY, 1);
+    private WeekFields SATURDAY_START = WeekFields.of(DayOfWeek.SATURDAY, 1);
+
+    public int getWeekNo(LocalDate date, int weekStartOn) {
+        if (weekStartOn == 1 || weekStartOn == 17) {
+            return date.get(SUNDAY_START.weekOfYear());
+        } else if (weekStartOn == 2 || weekStartOn == 11) {
+            return date.get(MONDAY_START.weekOfYear());
+        } else if (weekStartOn == 12) {
+            return date.get(TUESDAY_START.weekOfYear());
+        } else if (weekStartOn == 13) {
+            return date.get(WEDNESDAY_START.weekOfYear());
+        } else if (weekStartOn == 14) {
+            return date.get(THURSDAY_START.weekOfYear());
+        } else if (weekStartOn == 15) {
+            return date.get(FRIDAY_START.weekOfYear());
+        } else if (weekStartOn == 16) {
+            return date.get(SATURDAY_START.weekOfYear());
         } else {
-            cal.setFirstDayOfWeek(Calendar.MONDAY);
+            return date.get(WeekFields.ISO.weekOfYear());
         }
-        return cal.get(Calendar.WEEK_OF_YEAR);
     }
 
     @Override

Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekNumFunc.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekNumFunc.java?rev=1893852&r1=1893851&r2=1893852&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekNumFunc.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekNumFunc.java Sun Oct  3 13:17:48 2021
@@ -37,11 +37,32 @@ class TestWeekNumFunc {
 
     @Test
     void testEvaluate() {
-        assertEvaluateEquals(10.0, DateUtil.getExcelDate(LocalDate.parse("2012-03-09")));
-        //next assert returns 10 when it should be 11.0.
-        //assertEvaluateEquals(11.0, DateUtil.getExcelDate(LocalDate.parse("2012-03-09")), 2);
+        double date = DateUtil.getExcelDate(LocalDate.parse("2012-03-09"));
+        assertEvaluateEquals(10.0, date);
+        assertEvaluateEquals(10.0, date, 1);
+        assertEvaluateEquals(11.0, date, 2);
+        assertEvaluateEquals(11.0, date, 11);
+        assertEvaluateEquals(11.0, date, 12);
+        assertEvaluateEquals(11.0, date, 13);
+        assertEvaluateEquals(11.0, date, 14);
+        assertEvaluateEquals(11.0, date, 15);
+        assertEvaluateEquals(10.0, date, 16);
+        assertEvaluateEquals(10.0, date, 17);
+        assertEvaluateEquals(10.0, date, 21);
     }
 
+    @Test
+    void testEvaluateInvalid() {
+        assertEvaluateEquals("no args",       ErrorEval.VALUE_INVALID);
+        assertEvaluateEquals("too many args", ErrorEval.VALUE_INVALID, new NumberEval(1.0), new NumberEval(1.0), new NumberEval(1.0));
+        assertEvaluateEquals("negative date", ErrorEval.NUM_ERROR, new NumberEval(-1.0));
+        assertEvaluateEquals("cannot coerce serial_number to number", ErrorEval.VALUE_INVALID, new StringEval(""));
+        assertEvaluateEquals("cannot coerce return_type to number",   ErrorEval.NUM_ERROR, new NumberEval(1.0), new StringEval(""));
+        assertEvaluateEquals("return_type is blank",   ErrorEval.NUM_ERROR, new StringEval("2"), BlankEval.instance);
+        assertEvaluateEquals("invalid return_type",    ErrorEval.NUM_ERROR, new NumberEval(1.0), new NumberEval(18.0));
+    }
+
+
     private static final OperationEvaluationContext DEFAULT_CONTEXT =
             new OperationEvaluationContext(null, null, 0, 1, 0, null);
 

Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekdayFunc.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekdayFunc.java?rev=1893852&r1=1893851&r2=1893852&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekdayFunc.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestWeekdayFunc.java Sun Oct  3 13:17:48 2021
@@ -43,7 +43,6 @@ class TestWeekdayFunc {
         assertEquals(expected, result.getNumberValue(), TOLERANCE, formula);
     }
 
-
     @Test
     void testEvaluate() {
         assertEvaluateEquals(2.0,  1.0);



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org