Browse Source

[github-235] Fix date formatting for number cell values. Thanks to Anthony Schott. This close #235

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1889179 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_5_1_0
PJ Fanning 3 years ago
parent
commit
50cfe3c10e

+ 11
- 0
poi-ooxml/src/test/java/org/apache/poi/ss/tests/format/TestCellFormatPart.java View File

@@ -135,6 +135,17 @@ class TestCellFormatPart {
}
}

@Test
void testDateFormatNumbers() throws IOException {
TimeZone tz = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
try {
runFormatTests("DateFormatNumberTests.xlsx", Cell::getNumericCellValue);
} finally {
LocaleUtil.setUserTimeZone(tz);
}
}

@Test
void testElapsedFormat() throws IOException {
runFormatTests("ElapsedFormatTests.xlsx", Cell::getNumericCellValue);

+ 11
- 3
poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java View File

@@ -39,9 +39,11 @@ public class CellDateFormatter extends CellFormatter {
private final DateFormat dateFmt;
private String sFmt;

private final Calendar EXCEL_EPOCH_CAL =
private static final Calendar EXCEL_EPOCH_CAL =
LocaleUtil.getLocaleCalendar(1904, 0, 1);

private static final double NUM_MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;

private static /* final */ CellDateFormatter SIMPLE_DATE;

class DatePartHandler implements CellFormatPart.PartHandler {
@@ -177,12 +179,15 @@ public class CellDateFormatter extends CellFormatter {
value = 0.0;
if (value instanceof Number) {
Number num = (Number) value;
long v = num.longValue();
// Convert from fractional days to milliseconds. Excel always rounds up.
double v = Math.round(num.doubleValue() * NUM_MILLISECONDS_IN_DAY);
if (v == 0L) {
value = EXCEL_EPOCH_CAL.getTime();
} else {
Calendar c = (Calendar)EXCEL_EPOCH_CAL.clone();
c.add(Calendar.SECOND, (int)(v / 1000));
// If milliseconds were not requested in the format string, round the seconds.
int seconds = (int) (sFmt == null ? Math.round(v / 1000) : v / 1000);
c.add(Calendar.SECOND, seconds);
c.add(Calendar.MILLISECOND, (int)(v % 1000));
value = c.getTime();
}
@@ -201,6 +206,9 @@ public class CellDateFormatter extends CellFormatter {
int pos = toAppendTo.length();
try (Formatter formatter = new Formatter(toAppendTo, Locale.ROOT)) {
long msecs = dateObj.getTime() % 1000;
if (msecs < 0) {
msecs += 1000;
}
formatter.format(locale, sFmt, msecs / 1000.0);
}
toAppendTo.delete(pos, pos + 2);

BIN
test-data/spreadsheet/DateFormatNumberTests.xlsx View File


Loading…
Cancel
Save