Fix date parsing for XLS and ODS files to avoid timezone-dependency. (#3825)

Closes #3740.
This commit is contained in:
Antonin Delpeuch 2021-05-15 08:51:04 +02:00 committed by GitHub
parent bbec28e67d
commit 787c272fe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 2 deletions

View File

@ -40,9 +40,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.doc.table.OdfTable;

View File

@ -99,6 +99,7 @@ public class ParsingUtilities {
public static final ObjectWriter defaultWriter = mapper.writerWithView(JsonViews.NonSaveMode.class).with(defaultFilters);
public static final DateTimeFormatter ISO8601 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
private static final ZoneOffset defaultTimeOffset = OffsetDateTime.now().getOffset();
static public Properties parseUrlParameters(HttpServletRequest request) {
Properties options = new Properties();
@ -245,12 +246,28 @@ public class ParsingUtilities {
return o instanceof OffsetDateTime;
}
/**
* Converts an old-style Java Date to an OffsetDateTime,
* assuming the date is represented in the current default system timezone
* (which is what you get if the date was parsed using `Calendar.getDefault()`).
*
* @param date
* @return
*/
public static OffsetDateTime toDate(Date date) {
return date.toInstant().atOffset(ZoneOffset.UTC);
return date.toInstant().atOffset(defaultTimeOffset);
}
/**
* Converts an old-style Java Calendar to an OffsetDateTime,
* assuming the date is represented in the current default system timezone
* (which is what you get if the date was parsed using `Calendar.getDefault()`).
*
* @param date
* @return
*/
public static OffsetDateTime toDate(Calendar date) {
return date.toInstant().atOffset(ZoneOffset.UTC);
return date.toInstant().atOffset(defaultTimeOffset);
}
public static ObjectNode evaluateJsonStringToObjectNode(String optionsString) {

BIN
main/tests/data/dates.xls Normal file

Binary file not shown.

View File

@ -45,6 +45,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Month;
import java.time.OffsetDateTime;
import java.util.Calendar;
import java.util.Date;
@ -199,6 +201,39 @@ public class ExcelImporterTests extends ImporterTest {
Assert.fail(e.getMessage());
}
}
@Test
public void readExcelDates() throws FileNotFoundException, IOException {
ArrayNode sheets = ParsingUtilities.mapper.createArrayNode();
sheets.add(ParsingUtilities.mapper.readTree("{name: \"file-source#Test Sheet 0\", fileNameAndSheetIndex: \"file-source#0\", rows: 31, selected: true}"));
whenGetArrayOption("sheets", options, sheets);
whenGetIntegerOption("ignoreLines", options, 0);
whenGetIntegerOption("headerLines", options, 0);
whenGetIntegerOption("skipDataLines", options, 0);
whenGetIntegerOption("limit", options, -1);
whenGetBooleanOption("storeBlankCellsAsNulls", options, true);
InputStream stream = ClassLoader.getSystemResourceAsStream("dates.xls");
parseOneFile(SUT, stream);
// The original value reads 2021-04-18 in the Excel file.
// We make sure it is not shifted by a day because of timezone handling
Object cellValue = project.rows.get(0).getCellValue(0);
Assert.assertTrue(cellValue instanceof OffsetDateTime);
OffsetDateTime date = (OffsetDateTime) cellValue;
Assert.assertEquals(date.getYear(), 2021);
Assert.assertEquals(date.getMonth(), Month.APRIL);
Assert.assertEquals(date.getDayOfMonth(), 18);
// Same, with January 1st (in winter / no DST)
Object cellValue2 = project.rows.get(1).getCellValue(0);
Assert.assertTrue(cellValue instanceof OffsetDateTime);
OffsetDateTime date2 = (OffsetDateTime) cellValue2;
Assert.assertEquals(date2.getYear(), 2021);
Assert.assertEquals(date2.getMonth(), Month.JANUARY);
Assert.assertEquals(date2.getDayOfMonth(), 1);
}
@Test
public void readMultiSheetXls() throws FileNotFoundException, IOException{