Bug 60029: apply suggested fix and fix some IntelliJ warnings
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1765018 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b51eb49e58
commit
37116e84e5
@ -67,38 +67,33 @@ import org.apache.poi.util.LocaleUtil;
|
||||
*/
|
||||
public class Days360 extends Var2or3ArgFunction {
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
|
||||
double result;
|
||||
try {
|
||||
double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
|
||||
double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
|
||||
result = evaluate(d0, d1, false);
|
||||
return new NumberEval(evaluate(d0, d1, false));
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
return new NumberEval(result);
|
||||
}
|
||||
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
|
||||
ValueEval arg2) {
|
||||
double result;
|
||||
try {
|
||||
double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
|
||||
double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg2, srcRowIndex, srcColumnIndex);
|
||||
Boolean method = OperandResolver.coerceValueToBoolean(ve, false);
|
||||
result = evaluate(d0, d1, method == null ? false : method.booleanValue());
|
||||
return new NumberEval(evaluate(d0, d1, method != null && method.booleanValue()));
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
return new NumberEval(result);
|
||||
}
|
||||
|
||||
private static double evaluate(double d0, double d1, boolean method) {
|
||||
Calendar realStart = getDate(d0);
|
||||
Calendar realEnd = getDate(d1);
|
||||
int startingDate[] = getStartingDate(realStart, method);
|
||||
int endingDate[] = getEndingDate(realEnd, realStart, method);
|
||||
|
||||
int endingDate[] = getEndingDate(realEnd, startingDate, method);
|
||||
return
|
||||
(endingDate[0]*360+endingDate[1]*30+endingDate[2])-
|
||||
(startingDate[0]*360+startingDate[1]*30+startingDate[2]);
|
||||
@ -111,34 +106,32 @@ public class Days360 extends Var2or3ArgFunction {
|
||||
}
|
||||
|
||||
private static int[] getStartingDate(Calendar realStart, boolean method) {
|
||||
Calendar d = realStart;
|
||||
int yyyy = d.get(Calendar.YEAR);
|
||||
int mm = d.get(Calendar.MONTH);
|
||||
int dd = Math.min(30, d.get(Calendar.DAY_OF_MONTH));
|
||||
int yyyy = realStart.get(Calendar.YEAR);
|
||||
int mm = realStart.get(Calendar.MONTH);
|
||||
int dd = Math.min(30, realStart.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
if (method == false && isLastDayOfMonth(d)) dd = 30;
|
||||
if (!method && isLastDayOfMonth(realStart)) dd = 30;
|
||||
|
||||
return new int[]{yyyy,mm,dd};
|
||||
}
|
||||
|
||||
private static int[] getEndingDate(Calendar realEnd, Calendar realStart, boolean method) {
|
||||
Calendar d = realEnd;
|
||||
int yyyy = d.get(Calendar.YEAR);
|
||||
int mm = d.get(Calendar.MONTH);
|
||||
int dd = Math.min(30, d.get(Calendar.DAY_OF_MONTH));
|
||||
private static int[] getEndingDate(Calendar realEnd, int startingDate[], boolean method) {
|
||||
int yyyy = realEnd.get(Calendar.YEAR);
|
||||
int mm = realEnd.get(Calendar.MONTH);
|
||||
int dd = Math.min(30, realEnd.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
if (method == false && realEnd.get(Calendar.DAY_OF_MONTH) == 31) {
|
||||
if (realStart.get(Calendar.DAY_OF_MONTH) < 30) {
|
||||
d.set(Calendar.DAY_OF_MONTH, 1);
|
||||
d.add(Calendar.MONTH, 1);
|
||||
yyyy = d.get(Calendar.YEAR);
|
||||
mm = d.get(Calendar.MONTH);
|
||||
if (!method && realEnd.get(Calendar.DAY_OF_MONTH) == 31) {
|
||||
if (startingDate[2] < 30) {
|
||||
realEnd.set(Calendar.DAY_OF_MONTH, 1);
|
||||
realEnd.add(Calendar.MONTH, 1);
|
||||
yyyy = realEnd.get(Calendar.YEAR);
|
||||
mm = realEnd.get(Calendar.MONTH);
|
||||
dd = 1;
|
||||
} else {
|
||||
dd = 30;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new int[]{yyyy,mm,dd};
|
||||
}
|
||||
|
||||
|
@ -33,114 +33,133 @@ import org.junit.Test;
|
||||
|
||||
public final class TestDays360 {
|
||||
|
||||
/**
|
||||
* @param month 1-based
|
||||
*/
|
||||
private static Date makeDate(int year, int month, int day) {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
|
||||
return cal.getTime();
|
||||
}
|
||||
/**
|
||||
* @param month 1-based
|
||||
*/
|
||||
private static Date makeDate(int year, int month, int day) {
|
||||
Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
private static Date decrementDay(Date d) {
|
||||
Calendar c = LocaleUtil.getLocaleCalendar();
|
||||
c.setTime(d);
|
||||
c.add(Calendar.DAY_OF_MONTH, -1);
|
||||
return c.getTime();
|
||||
}
|
||||
private static Date decrementDay(Date d) {
|
||||
Calendar c = LocaleUtil.getLocaleCalendar();
|
||||
c.setTime(d);
|
||||
c.add(Calendar.DAY_OF_MONTH, -1);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasic() {
|
||||
confirm(120, 2009, 1, 15, 2009, 5, 15);
|
||||
confirm(158, 2009, 1, 26, 2009, 7, 4);
|
||||
@Test
|
||||
public void testBasic() {
|
||||
confirm(120, 2009, 1, 15, 2009, 5, 15);
|
||||
confirm(158, 2009, 1, 26, 2009, 7, 4);
|
||||
|
||||
// same results in leap years
|
||||
confirm(120, 2008, 1, 15, 2008, 5, 15);
|
||||
confirm(158, 2008, 1, 26, 2008, 7, 4);
|
||||
// same results in leap years
|
||||
confirm(120, 2008, 1, 15, 2008, 5, 15);
|
||||
confirm(158, 2008, 1, 26, 2008, 7, 4);
|
||||
|
||||
// longer time spans
|
||||
confirm(562, 2008, 8, 11, 2010, 3, 3);
|
||||
confirm(916, 2007, 2, 23, 2009, 9, 9);
|
||||
|
||||
// other tests
|
||||
confirm(1, makeDate(1993, 2, 28), makeDate(1993, 3, 1), false);
|
||||
// longer time spans
|
||||
confirm(562, 2008, 8, 11, 2010, 3, 3);
|
||||
confirm(916, 2007, 2, 23, 2009, 9, 9);
|
||||
|
||||
// other tests
|
||||
confirm(1, makeDate(1993, 2, 28), makeDate(1993, 3, 1), false);
|
||||
confirm(1, makeDate(1996, 2, 29), makeDate(1996, 3, 1), false);
|
||||
confirm(-2, makeDate(1993, 2, 28), makeDate(1993, 2, 28), false);
|
||||
confirm(3, makeDate(1993, 2, 28), makeDate(1993, 3, 1), true);
|
||||
confirm(2, makeDate(1996, 2, 29), makeDate(1996, 3, 1), true);
|
||||
}
|
||||
|
||||
private static void confirm(int expResult, int y1, int m1, int d1, int y2, int m2, int d2) {
|
||||
confirm(expResult, makeDate(y1, m1, d1), makeDate(y2, m2, d2), false);
|
||||
confirm(-expResult, makeDate(y2, m2, d2), makeDate(y1, m1, d1), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The <tt>method</tt> parameter only makes a difference when the second parameter
|
||||
* is the last day of the month that does <em>not</em> have 30 days.
|
||||
*/
|
||||
@Test
|
||||
public void testMonthBoundaries() {
|
||||
// jan
|
||||
confirmMonthBoundary(false, 2001, 1, 0, 0, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 1, 0, 0, 1, 2, 3);
|
||||
// feb
|
||||
confirmMonthBoundary(false, 2001, 2,-2, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 2, 0, 1, 2, 3, 4);
|
||||
// mar
|
||||
confirmMonthBoundary(false, 2001, 3, 0, 0, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 3, 0, 0, 1, 2, 3);
|
||||
// apr
|
||||
confirmMonthBoundary(false, 2001, 4, 0, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 4, 0, 1, 2, 3, 4);
|
||||
// may
|
||||
confirmMonthBoundary(false, 2001, 5, 0, 0, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 5, 0, 0, 1, 2, 3);
|
||||
// jun
|
||||
confirmMonthBoundary(false, 2001, 6, 0, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 6, 0, 1, 2, 3, 4);
|
||||
// from https://support.office.com/en-us/article/DAYS360-function-B9A509FD-49EF-407E-94DF-0CBDA5718C2A
|
||||
confirm(1, makeDate(2011, 1, 30), makeDate(2011, 2, 1), false);
|
||||
confirm(360, makeDate(2011, 1, 1), makeDate(2011, 12, 31), false);
|
||||
confirm(30, makeDate(2011, 1, 1), makeDate(2011, 2, 1), false);
|
||||
}
|
||||
|
||||
private static void confirm(int expResult, int y1, int m1, int d1, int y2, int m2, int d2) {
|
||||
confirm(expResult, makeDate(y1, m1, d1), makeDate(y2, m2, d2), false);
|
||||
confirm(-expResult, makeDate(y2, m2, d2), makeDate(y1, m1, d1), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The <tt>method</tt> parameter only makes a difference when the second parameter
|
||||
* is the last day of the month that does <em>not</em> have 30 days.
|
||||
*/
|
||||
@Test
|
||||
public void testMonthBoundaries() {
|
||||
// jan
|
||||
confirmMonthBoundary(false, 2001, 1, 0, 0, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 1, 0, 0, 1, 2, 3);
|
||||
// feb
|
||||
confirmMonthBoundary(false, 2001, 2,-2, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 2, 0, 1, 2, 3, 4);
|
||||
// mar
|
||||
confirmMonthBoundary(false, 2001, 3, 0, 0, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 3, 0, 0, 1, 2, 3);
|
||||
// apr
|
||||
confirmMonthBoundary(false, 2001, 4, 0, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 4, 0, 1, 2, 3, 4);
|
||||
// may
|
||||
confirmMonthBoundary(false, 2001, 5, 0, 0, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 5, 0, 0, 1, 2, 3);
|
||||
// jun
|
||||
confirmMonthBoundary(false, 2001, 6, 0, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2001, 6, 0, 1, 2, 3, 4);
|
||||
// leap year
|
||||
confirmMonthBoundary(false, 2012, 2, -1, 1, 2, 3, 4);
|
||||
confirmMonthBoundary(true, 2012, 2, 0, 1, 2, 3, 4);
|
||||
}
|
||||
|
||||
// bug 60029
|
||||
Date start = makeDate(2018, 2, 28);
|
||||
Date end = makeDate(2018, 3, 31);
|
||||
confirm(30, start, end, false);
|
||||
|
||||
// examples from https://support.office.com/en-us/article/DAYS360-function-B9A509FD-49EF-407E-94DF-0CBDA5718C2A
|
||||
start = makeDate(2011, 1, 30);
|
||||
end = makeDate(2011, 2, 1);
|
||||
confirm(1, start, end, false);
|
||||
|
||||
start = makeDate(2011, 1, 1);
|
||||
end = makeDate(2011, 12, 31);
|
||||
confirm(360, start, end, false);
|
||||
|
||||
start = makeDate(2011, 1, 1);
|
||||
end = makeDate(2011, 2, 1);
|
||||
confirm(30, start, end, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param monthNo 1-based
|
||||
* @param diffs
|
||||
*/
|
||||
private static void confirmMonthBoundary(boolean method, int year, int monthNo, int...diffs) {
|
||||
Date firstDayOfNextMonth = makeDate(year, monthNo+1, 1);
|
||||
Date secondArg = decrementDay(firstDayOfNextMonth);
|
||||
Date firstArg = secondArg;
|
||||
/**
|
||||
* @param monthNo 1-based
|
||||
*/
|
||||
private static void confirmMonthBoundary(boolean method, int year, int monthNo, int...diffs) {
|
||||
Date firstDayOfNextMonth = makeDate(year, monthNo+1, 1);
|
||||
Date secondArg = decrementDay(firstDayOfNextMonth);
|
||||
Date firstArg = secondArg;
|
||||
|
||||
for (int expResult : diffs) {
|
||||
confirm(expResult, firstArg, secondArg, method);
|
||||
firstArg = decrementDay(firstArg);
|
||||
}
|
||||
for (int expResult : diffs) {
|
||||
confirm(expResult, firstArg, secondArg, method);
|
||||
firstArg = decrementDay(firstArg);
|
||||
}
|
||||
|
||||
}
|
||||
private static void confirm(int expResult, Date firstArg, Date secondArg, boolean method) {
|
||||
}
|
||||
private static void confirm(int expResult, Date firstArg, Date secondArg, boolean method) {
|
||||
ValueEval ve;
|
||||
if (method) {
|
||||
ve = invokeDays360(convert(firstArg), convert(secondArg), BoolEval.TRUE);
|
||||
} else {
|
||||
ve = invokeDays360(convert(firstArg), convert(secondArg));
|
||||
}
|
||||
assertTrue("wrong return type (" + ve.getClass().getName() + ")", ve instanceof NumberEval);
|
||||
|
||||
ValueEval ve;
|
||||
if (method) {
|
||||
// TODO enable 3rd arg -
|
||||
ve = invokeDays360(convert(firstArg), convert(secondArg), BoolEval.valueOf(method));
|
||||
} else {
|
||||
ve = invokeDays360(convert(firstArg), convert(secondArg));
|
||||
}
|
||||
assertTrue("wrong return type (" + ve.getClass().getName() + ")", ve instanceof NumberEval);
|
||||
|
||||
NumberEval numberEval = (NumberEval) ve;
|
||||
String err = String.format(Locale.ROOT, "days360(%tF,%tF,%b) wrong result", firstArg, secondArg, method);
|
||||
assertEquals(err, expResult, numberEval.getNumberValue(), 0);
|
||||
}
|
||||
|
||||
private static ValueEval invokeDays360(ValueEval...args) {
|
||||
return new Days360().evaluate(args, -1, -1);
|
||||
}
|
||||
|
||||
private static NumberEval convert(Date d) {
|
||||
return new NumberEval(HSSFDateUtil.getExcelDate(d));
|
||||
}
|
||||
NumberEval numberEval = (NumberEval) ve;
|
||||
String err = String.format(Locale.ROOT, "days360(%tF,%tF,%b) wrong result", firstArg, secondArg, method);
|
||||
assertEquals(err, expResult, numberEval.getNumberValue(), 0);
|
||||
}
|
||||
|
||||
private static ValueEval invokeDays360(ValueEval...args) {
|
||||
return new Days360().evaluate(args, -1, -1);
|
||||
}
|
||||
|
||||
private static NumberEval convert(Date d) {
|
||||
return new NumberEval(HSSFDateUtil.getExcelDate(d));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user