[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
This commit is contained in:
PJ Fanning 2021-04-25 17:16:05 +00:00
parent 1d594451d8
commit 50cfe3c10e
3 changed files with 22 additions and 3 deletions

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);

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);

Binary file not shown.