mirror of https://github.com/apache/poi.git
[bug-65606] try to fix weeknum function
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1893852 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4cce90f31e
commit
9244ab3646
|
@ -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 Fixed2ArgFunction implements FreeRefFunction {
|
|||
} 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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ class TestWeekdayFunc {
|
|||
assertEquals(expected, result.getNumberValue(), TOLERANCE, formula);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testEvaluate() {
|
||||
assertEvaluateEquals(2.0, 1.0);
|
||||
|
|
Loading…
Reference in New Issue