Fix bug #48528 - support negative arguments to the DATE() function
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1331796 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b956b78e91
commit
8a13b1bf04
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.9-beta1" date="2012-??-??">
|
<release version="3.9-beta1" date="2012-??-??">
|
||||||
|
<action dev="poi-developers" type="fix">48528 - support negative arguments to the DATE() function</action>
|
||||||
<action dev="poi-developers" type="fix">53092 - allow specifying of a TimeZone to DateUtil.getJavaDate(), for when it is known that a file comes from a different (known) timezone to the current machine</action>
|
<action dev="poi-developers" type="fix">53092 - allow specifying of a TimeZone to DateUtil.getJavaDate(), for when it is known that a file comes from a different (known) timezone to the current machine</action>
|
||||||
<action dev="poi-developers" type="fix">53043 - don't duplicate hyperlink relationships when saving XSSF file</action>
|
<action dev="poi-developers" type="fix">53043 - don't duplicate hyperlink relationships when saving XSSF file</action>
|
||||||
<action dev="poi-developers" type="fix">53101 - fixed evaluation of SUM over cell range > 255</action>
|
<action dev="poi-developers" type="fix">53101 - fixed evaluation of SUM over cell range > 255</action>
|
||||||
|
@ -54,16 +54,29 @@ public final class DateFunc extends Fixed3ArgFunction {
|
|||||||
return new NumberEval(result);
|
return new NumberEval(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note - works with Java Calendar months, not Excel months
|
||||||
|
*/
|
||||||
private static double evaluate(int year, int month, int pDay) throws EvaluationException {
|
private static double evaluate(int year, int month, int pDay) throws EvaluationException {
|
||||||
|
// We don't support negative years yet
|
||||||
if (year < 0 || month < 0 || pDay < 0) {
|
if (year < 0) {
|
||||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
}
|
}
|
||||||
|
// Negative months are fairly easy
|
||||||
|
while (month < 0) {
|
||||||
|
year--;
|
||||||
|
month += 12;
|
||||||
|
}
|
||||||
|
// Negative days are handled by the Java Calendar
|
||||||
|
|
||||||
|
// Excel has bugs around leap years in 1900, handle them
|
||||||
|
// Special case for the non-existant 1900 leap year
|
||||||
if (year == 1900 && month == Calendar.FEBRUARY && pDay == 29) {
|
if (year == 1900 && month == Calendar.FEBRUARY && pDay == 29) {
|
||||||
return 60.0;
|
return 60.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If they give a date in 1900 in Jan/Feb, with the days
|
||||||
|
// putting it past the leap year, adjust
|
||||||
int day = pDay;
|
int day = pDay;
|
||||||
if (year == 1900) {
|
if (year == 1900) {
|
||||||
if ((month == Calendar.JANUARY && day >= 60) ||
|
if ((month == Calendar.JANUARY && day >= 60) ||
|
||||||
@ -72,12 +85,24 @@ public final class DateFunc extends Fixed3ArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn this into a Java date
|
||||||
Calendar c = new GregorianCalendar();
|
Calendar c = new GregorianCalendar();
|
||||||
|
|
||||||
c.set(year, month, day, 0, 0, 0);
|
c.set(year, month, day, 0, 0, 0);
|
||||||
c.set(Calendar.MILLISECOND, 0);
|
c.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
return DateUtil.getExcelDate(c.getTime(), false); // TODO - fix 1900/1904 problem
|
// Handle negative days of the week, that pull us across
|
||||||
|
// the 29th of Feb 1900
|
||||||
|
if (pDay < 0 && c.get(Calendar.YEAR) == 1900 &&
|
||||||
|
month > Calendar.FEBRUARY &&
|
||||||
|
c.get(Calendar.MONTH) < Calendar.MARCH) {
|
||||||
|
c.add(Calendar.DATE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Identify if we're doing 1900 or 1904 date windowing
|
||||||
|
boolean use1904windowing = false;
|
||||||
|
|
||||||
|
// Have this Java date turned back into an Excel one
|
||||||
|
return DateUtil.getExcelDate(c.getTime(), use1904windowing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getYear(double d) {
|
private static int getYear(double d) {
|
||||||
|
@ -293,6 +293,48 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDateWithNegativeParts_bug48528() {
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
HSSFSheet sheet = wb.createSheet("Sheet1");
|
||||||
|
HSSFRow row = sheet.createRow(1);
|
||||||
|
HSSFCell cell = row.createCell(0);
|
||||||
|
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||||
|
|
||||||
|
// 5th Feb 2012 = 40944
|
||||||
|
// 1st Feb 2012 = 40940
|
||||||
|
// 5th Jan 2012 = 40913
|
||||||
|
// 5th Dec 2011 = 40882
|
||||||
|
// 5th Feb 2011 = 40579
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2,1)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40940.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2,1+4)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40944.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2-1,1+4)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2,1-27)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2-2,1+4)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2,1-58)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
|
||||||
|
cell.setCellFormula("DATE(2012,2-12,1+4)");
|
||||||
|
fe.notifyUpdateCell(cell);
|
||||||
|
assertEquals(40579.0, fe.evaluate(cell).getNumberValue());
|
||||||
|
}
|
||||||
|
|
||||||
private static final class EvalListener extends EvaluationListener {
|
private static final class EvalListener extends EvaluationListener {
|
||||||
private int _countCacheHits;
|
private int _countCacheHits;
|
||||||
private int _countCacheMisses;
|
private int _countCacheMisses;
|
||||||
|
Loading…
Reference in New Issue
Block a user