diff --git a/spring-batch-excel/src/main/java/org/springframework/batch/extensions/excel/IsoFormattingDateDataFormatter.java b/spring-batch-excel/src/main/java/org/springframework/batch/extensions/excel/IsoFormattingDateDataFormatter.java index 3a83e4c..4cb48a0 100644 --- a/spring-batch-excel/src/main/java/org/springframework/batch/extensions/excel/IsoFormattingDateDataFormatter.java +++ b/spring-batch-excel/src/main/java/org/springframework/batch/extensions/excel/IsoFormattingDateDataFormatter.java @@ -28,7 +28,7 @@ import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.FormulaEvaluator; /** - * Specialized subclass for additionally formatting the date into an ISO date/time. + * Specialized subclass for formatting the date into an ISO date/time and ignore the format as given in the Excel file. * * @author Marten Deinum * @@ -44,6 +44,15 @@ public class IsoFormattingDateDataFormatter extends DataFormatter { super(locale); } + @Override + public String formatRawCellContents(double value, int formatIndex, String formatString, boolean use1904Windowing) { + if (DateUtil.isADateFormat(formatIndex, formatString) && DateUtil.isValidExcelDate(value)) { + return super.formatRawCellContents(value, formatIndex, "yyyy-MM-ddTHH:mm:ss", + use1904Windowing); + } + return super.formatRawCellContents(value, formatIndex, formatString, use1904Windowing); + } + @Override public String formatCellValue(Cell cell, FormulaEvaluator evaluator, ConditionalFormattingEvaluator cfEvaluator) { if (cell == null) { @@ -60,7 +69,7 @@ public class IsoFormattingDateDataFormatter extends DataFormatter { if (cellType == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell, cfEvaluator)) { LocalDateTime value = cell.getLocalDateTimeCellValue(); - return (value != null) ? value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME) : ""; + return (value != null) ? value.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : ""; } return super.formatCellValue(cell, evaluator, cfEvaluator); } diff --git a/spring-batch-excel/src/test/java/org/springframework/batch/extensions/excel/poi/PoiItemReaderTypesTest.java b/spring-batch-excel/src/test/java/org/springframework/batch/extensions/excel/poi/PoiItemReaderTypesTest.java new file mode 100644 index 0000000..42cfdae --- /dev/null +++ b/spring-batch-excel/src/test/java/org/springframework/batch/extensions/excel/poi/PoiItemReaderTypesTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.extensions.excel.poi; + +import java.util.Locale; + +import org.junit.jupiter.api.Test; + +import org.springframework.batch.extensions.excel.mapping.PassThroughRowMapper; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.ClassPathResource; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class PoiItemReaderTypesTest { + + @Test + public void shouldBeAbleToReadMultipleTypes() throws Exception { + var reader = new PoiItemReader(); + reader.setResource(new ClassPathResource("types.xls")); + reader.setRowMapper(new PassThroughRowMapper()); + reader.setLinesToSkip(1); // Skip header + reader.setUserLocale(Locale.US); // Use a Locale to not be dependent on environment + reader.afterPropertiesSet(); + + + reader.open(new ExecutionContext()); + + var row1 = reader.read(); + var row2 = reader.read(); + assertThat(row1).containsExactly("1", "1.0", "5/12/24", "13:14:55", "5/12/24 13:14", "hello world"); + assertThat(row2).containsExactly("2", "2.5", "8/8/23", "11:12:13", "8/8/23 11:12", "world hello"); + + } + + @Test + public void shouldBeAbleToReadMultipleTypesWithDatesAsIso() throws Exception { + var reader = new PoiItemReader(); + reader.setResource(new ClassPathResource("types.xls")); + reader.setRowMapper(new PassThroughRowMapper()); + reader.setLinesToSkip(1); // Skip header + reader.setUserLocale(Locale.US); // Use a Locale to not be dependent on environment + reader.setDatesAsIso(true); + reader.afterPropertiesSet(); + + reader.open(new ExecutionContext()); + + var row1 = reader.read(); + var row2 = reader.read(); + assertThat(row1).containsExactly("1", "1.0", "2024-05-12T00:00:00", "1899-12-31T13:14:55", "2024-05-12T13:14:55", "hello world"); + assertThat(row2).containsExactly("2", "2.5", "2023-08-08T00:00:00", "1899-12-31T11:12:13", "2023-08-08T11:12:13", "world hello"); + + } +} diff --git a/spring-batch-excel/src/test/java/org/springframework/batch/extensions/excel/streaming/StreamingXlsxTypesTest.java b/spring-batch-excel/src/test/java/org/springframework/batch/extensions/excel/streaming/StreamingXlsxTypesTest.java new file mode 100644 index 0000000..948f0e2 --- /dev/null +++ b/spring-batch-excel/src/test/java/org/springframework/batch/extensions/excel/streaming/StreamingXlsxTypesTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.extensions.excel.streaming; + +import java.util.Locale; + +import org.junit.jupiter.api.Test; + +import org.springframework.batch.extensions.excel.mapping.PassThroughRowMapper; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.ClassPathResource; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StreamingXlsxTypesTest { + + @Test + public void shouldBeAbleToReadMultipleTypes() throws Exception { + var reader = new StreamingXlsxItemReader(); + reader.setResource(new ClassPathResource("types.xlsx")); + reader.setRowMapper(new PassThroughRowMapper()); + reader.setLinesToSkip(1); // Skip header + reader.setUserLocale(Locale.US); // Use a Locale to not be dependent on environment + reader.afterPropertiesSet(); + + reader.open(new ExecutionContext()); + + var row1 = reader.read(); + var row2 = reader.read(); + assertThat(row1).containsExactly("1", "1.0", "5/12/24", "13:14:55", "5/12/24 13:14", "hello world"); + assertThat(row2).containsExactly("2", "2.5", "8/8/23", "11:12:13", "8/8/23 11:12", "world hello"); + + } + + @Test + public void shouldBeAbleToReadMultipleTypesWithDatesAsIso() throws Exception { + var reader = new StreamingXlsxItemReader(); + reader.setResource(new ClassPathResource("types.xlsx")); + reader.setRowMapper(new PassThroughRowMapper()); + reader.setLinesToSkip(1); // Skip header + reader.setUserLocale(Locale.US); // Use a Locale to not be dependent on environment + reader.setDatesAsIso(true); + reader.afterPropertiesSet(); + + reader.open(new ExecutionContext()); + + var row1 = reader.read(); + var row2 = reader.read(); + assertThat(row1).containsExactly("1", "1.0", "2024-05-12T00:00:00", "1899-12-31T13:14:55", "2024-05-12T13:14:55", "hello world"); + assertThat(row2).containsExactly("2", "2.5", "2023-08-08T00:00:00", "1899-12-31T11:12:13", "2023-08-08T11:12:13", "world hello"); + + } + +} diff --git a/spring-batch-excel/src/test/resources/types.xls b/spring-batch-excel/src/test/resources/types.xls new file mode 100644 index 0000000..83b0c3f Binary files /dev/null and b/spring-batch-excel/src/test/resources/types.xls differ diff --git a/spring-batch-excel/src/test/resources/types.xlsx b/spring-batch-excel/src/test/resources/types.xlsx new file mode 100644 index 0000000..be62ebe Binary files /dev/null and b/spring-batch-excel/src/test/resources/types.xlsx differ