From 6c62e2a41886765950495cc5d020387cff7f863d Mon Sep 17 00:00:00 2001 From: Anubyss-mihail Date: Wed, 9 Sep 2026 17:34:12 +0200 Subject: [PATCH 1/3] feat: add SQL Date converters --- .../converters/DefaultConverterLoader.java | 7 ++ .../sqldate/SqlDateDateConverter.java | 53 +++++++++++ .../sqldate/SqlDateNumberConverter.java | 62 +++++++++++++ .../sqldate/SqlDateStringConverter.java | 75 ++++++++++++++++ .../sqldate/SqlDateConverterTest.java | 88 +++++++++++++++++++ 5 files changed, 285 insertions(+) create mode 100644 fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java create mode 100644 fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java create mode 100644 fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java create mode 100644 fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/DefaultConverterLoader.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/DefaultConverterLoader.java index f17d9b62c..665e2dac2 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/DefaultConverterLoader.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/DefaultConverterLoader.java @@ -73,6 +73,9 @@ import org.apache.fesod.sheet.converters.shortconverter.ShortBooleanConverter; import org.apache.fesod.sheet.converters.shortconverter.ShortNumberConverter; import org.apache.fesod.sheet.converters.shortconverter.ShortStringConverter; +import org.apache.fesod.sheet.converters.sqldate.SqlDateDateConverter; +import org.apache.fesod.sheet.converters.sqldate.SqlDateNumberConverter; +import org.apache.fesod.sheet.converters.sqldate.SqlDateStringConverter; import org.apache.fesod.sheet.converters.string.StringBooleanConverter; import org.apache.fesod.sheet.converters.string.StringErrorConverter; import org.apache.fesod.sheet.converters.string.StringNumberConverter; @@ -142,6 +145,8 @@ private static void initAllConverter() { putAllConverter(new ShortBooleanConverter()); putAllConverter(new ShortNumberConverter()); putAllConverter(new ShortStringConverter()); + putAllConverter(new SqlDateNumberConverter()); + putAllConverter(new SqlDateStringConverter()); putAllConverter(new StringBooleanConverter()); putAllConverter(new StringNumberConverter()); @@ -157,6 +162,7 @@ private static void initDefaultWriteConverter() { putWriteConverter(new BooleanBooleanConverter()); putWriteConverter(new ByteNumberConverter()); putWriteConverter(new DateDateConverter()); + putWriteConverter(new SqlDateDateConverter()); putWriteConverter(new LocalDateTimeDateConverter()); putWriteConverter(new LocalDateDateConverter()); putWriteConverter(new LocalTimeDateConverter()); @@ -178,6 +184,7 @@ private static void initDefaultWriteConverter() { putWriteStringConverter(new BooleanStringConverter()); putWriteStringConverter(new ByteStringConverter()); putWriteStringConverter(new DateStringConverter()); + putWriteStringConverter(new SqlDateStringConverter()); putWriteStringConverter(new LocalDateStringConverter()); putWriteStringConverter(new LocalDateTimeStringConverter()); putWriteStringConverter(new LocalTimeStringConverter()); diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java new file mode 100644 index 000000000..37fcd5152 --- /dev/null +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.fesod.sheet.converters.sqldate; + +import java.sql.Date; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.util.DateUtils; +import org.apache.fesod.sheet.util.WorkBookUtil; + +/** + * Date and date converter + * + * + */ +public class SqlDateDateConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return Date.class; + } + + @Override + public WriteCellData convertToExcelData( + Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) + throws Exception { + WriteCellData cellData = new WriteCellData<>(value); + String format = null; + if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) { + format = contentProperty.getDateTimeFormatProperty().getFormat(); + } + WorkBookUtil.fillDataFormat(cellData, format, DateUtils.defaultDateFormat); + return cellData; + } +} diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java new file mode 100644 index 000000000..f37325894 --- /dev/null +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.fesod.sheet.converters.sqldate; + +import java.math.BigDecimal; +import java.sql.Date; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.util.DateUtils; +import org.apache.poi.ss.usermodel.DateUtil; + +/** + * Converter for {@link java.sql.Date} and Excel number cells. + */ +public class SqlDateNumberConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Date.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.NUMBER; + } + + @Override + public Date convertToJavaData( + ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + java.util.Date date = DateUtils.getJavaDate( + cellData.getNumberValue().doubleValue(), DateUtils.isDate1904(contentProperty, globalConfiguration)); + return new Date(date.getTime()); + } + + @Override + public WriteCellData convertToExcelData( + Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return new WriteCellData<>(BigDecimal.valueOf( + DateUtil.getExcelDate(value, DateUtils.isDate1904(contentProperty, globalConfiguration)))); + } +} diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java new file mode 100644 index 000000000..729478b19 --- /dev/null +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.fesod.sheet.converters.sqldate; + +import java.sql.Date; +import java.text.ParseException; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.util.DateUtils; + +/** + * Date and string converter + * + * + */ +public class SqlDateStringConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return Date.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Date convertToJavaData( + ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) + throws ParseException { + java.util.Date date; + + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + date = DateUtils.parseDate(cellData.getStringValue(), null); + } else { + date = DateUtils.parseDate( + cellData.getStringValue(), + contentProperty.getDateTimeFormatProperty().getFormat()); + } + + return new Date(date.getTime()); + } + + @Override + public WriteCellData convertToExcelData( + Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return new WriteCellData<>(DateUtils.format(value, null)); + } else { + return new WriteCellData<>(DateUtils.format( + value, contentProperty.getDateTimeFormatProperty().getFormat())); + } + } +} diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java new file mode 100644 index 000000000..b1a588667 --- /dev/null +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.fesod.sheet.converters.sqldate; + +import java.math.BigDecimal; +import java.sql.Date; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.DateTimeFormatProperty; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.testkit.Tags; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +/** + * Tests SQL date converters. + */ +@Tag(Tags.UNIT) +class SqlDateConverterTest { + + @Test + void dateConverterSupportsSqlDate() { + SqlDateDateConverter converter = new SqlDateDateConverter(); + + Assertions.assertEquals(Date.class, converter.supportJavaTypeKey()); + } + + @Test + void numberConverterConvertsToJavaData() { + SqlDateNumberConverter converter = new SqlDateNumberConverter(); + ReadCellData cellData = new ReadCellData<>(BigDecimal.ONE); + + Date actual = converter.convertToJavaData(cellData, null, new GlobalConfiguration()); + + Assertions.assertNotNull(actual); + Assertions.assertEquals(Date.class, actual.getClass()); + Assertions.assertEquals(CellDataTypeEnum.NUMBER, converter.supportExcelTypeKey()); + } + + @Test + void stringConverterConvertsToJavaData() throws Exception { + SqlDateStringConverter converter = new SqlDateStringConverter(); + ExcelContentProperty contentProperty = contentProperty("yyyy-MM-dd"); + ReadCellData cellData = new ReadCellData<>("2026-09-06"); + + Date actual = converter.convertToJavaData(cellData, contentProperty, new GlobalConfiguration()); + + Assertions.assertEquals(Date.valueOf("2026-09-06"), actual); + Assertions.assertEquals(CellDataTypeEnum.STRING, converter.supportExcelTypeKey()); + } + + @Test + void stringConverterConvertsToExcelData() { + SqlDateStringConverter converter = new SqlDateStringConverter(); + ExcelContentProperty contentProperty = contentProperty("yyyy-MM-dd"); + + WriteCellData actual = + converter.convertToExcelData(Date.valueOf("2026-09-06"), contentProperty, new GlobalConfiguration()); + + Assertions.assertEquals("2026-09-06", actual.getStringValue()); + } + + private static ExcelContentProperty contentProperty(String format) { + ExcelContentProperty contentProperty = new ExcelContentProperty(); + contentProperty.setDateTimeFormatProperty(new DateTimeFormatProperty(format, null)); + return contentProperty; + } +} From 220c4632d26919e60e466837c86a329dad961b28 Mon Sep 17 00:00:00 2001 From: Anubyss-mihail Date: Sun, 13 Sep 2026 05:55:40 +0200 Subject: [PATCH 2/3] fix: address SQL Date converter review feedback --- .../sqldate/SqlDateDateConverter.java | 4 +- .../sqldate/SqlDateStringConverter.java | 4 +- .../sqldate/SqlDateConverterTest.java | 48 ++++++++++++++++++- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java index 37fcd5152..bb9f1ca85 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateDateConverter.java @@ -28,9 +28,7 @@ import org.apache.fesod.sheet.util.WorkBookUtil; /** - * Date and date converter - * - * + * Converter for {@link java.sql.Date} and Excel date cells. */ public class SqlDateDateConverter implements Converter { @Override diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java index 729478b19..eaf4807bd 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateStringConverter.java @@ -30,9 +30,7 @@ import org.apache.fesod.sheet.util.DateUtils; /** - * Date and string converter - * - * + * Converter for {@link java.sql.Date} and Excel string cells. */ public class SqlDateStringConverter implements Converter { @Override diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java index b1a588667..2df9f1e0f 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/converters/sqldate/SqlDateConverterTest.java @@ -28,6 +28,8 @@ import org.apache.fesod.sheet.metadata.property.DateTimeFormatProperty; import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import org.apache.fesod.sheet.testkit.Tags; +import org.apache.fesod.sheet.util.DateUtils; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -38,6 +40,11 @@ @Tag(Tags.UNIT) class SqlDateConverterTest { + @AfterEach + void tearDown() { + DateUtils.removeThreadLocalCache(); + } + @Test void dateConverterSupportsSqlDate() { SqlDateDateConverter converter = new SqlDateDateConverter(); @@ -45,6 +52,17 @@ void dateConverterSupportsSqlDate() { Assertions.assertEquals(Date.class, converter.supportJavaTypeKey()); } + @Test + void dateConverterConvertsToExcelData() throws Exception { + SqlDateDateConverter converter = new SqlDateDateConverter(); + ExcelContentProperty contentProperty = contentProperty("yyyy-MM-dd"); + Date value = Date.valueOf("2026-09-06"); + + WriteCellData actual = converter.convertToExcelData(value, contentProperty, new GlobalConfiguration()); + + Assertions.assertEquals(value.toLocalDate().atStartOfDay(), actual.getDateValue()); + } + @Test void numberConverterConvertsToJavaData() { SqlDateNumberConverter converter = new SqlDateNumberConverter(); @@ -57,6 +75,30 @@ void numberConverterConvertsToJavaData() { Assertions.assertEquals(CellDataTypeEnum.NUMBER, converter.supportExcelTypeKey()); } + @Test + void numberConverterUses1904Windowing() { + SqlDateNumberConverter converter = new SqlDateNumberConverter(); + GlobalConfiguration configuration = new GlobalConfiguration(); + configuration.setUse1904windowing(Boolean.TRUE); + ReadCellData cellData = new ReadCellData<>(BigDecimal.ONE); + + Date actual = converter.convertToJavaData(cellData, null, configuration); + + Assertions.assertEquals(new Date(DateUtils.getJavaDate(1, true).getTime()), actual); + } + + @Test + void numberConverterPrefersExplicitWindowingOverGlobal() { + SqlDateNumberConverter converter = new SqlDateNumberConverter(); + GlobalConfiguration configuration = new GlobalConfiguration(); + configuration.setUse1904windowing(Boolean.TRUE); + ExcelContentProperty contentProperty = contentProperty("yyyy-MM-dd", Boolean.FALSE); + + Date actual = converter.convertToJavaData(new ReadCellData<>(BigDecimal.ONE), contentProperty, configuration); + + Assertions.assertEquals(new Date(DateUtils.getJavaDate(1, false).getTime()), actual); + } + @Test void stringConverterConvertsToJavaData() throws Exception { SqlDateStringConverter converter = new SqlDateStringConverter(); @@ -81,8 +123,12 @@ void stringConverterConvertsToExcelData() { } private static ExcelContentProperty contentProperty(String format) { + return contentProperty(format, null); + } + + private static ExcelContentProperty contentProperty(String format, Boolean use1904windowing) { ExcelContentProperty contentProperty = new ExcelContentProperty(); - contentProperty.setDateTimeFormatProperty(new DateTimeFormatProperty(format, null)); + contentProperty.setDateTimeFormatProperty(new DateTimeFormatProperty(format, use1904windowing)); return contentProperty; } } From 51629d0d322c0f5291a8950595b652887375d04d Mon Sep 17 00:00:00 2001 From: Anubyss-mihail Date: Thu, 24 Sep 2026 19:54:18 +0200 Subject: [PATCH 3/3] fix sql date number conversion --- .../converters/sqldate/SqlDateNumberConverter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java index f37325894..f2a524e7e 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/converters/sqldate/SqlDateNumberConverter.java @@ -21,6 +21,8 @@ import java.math.BigDecimal; import java.sql.Date; +import java.time.LocalDate; + import org.apache.fesod.sheet.converters.Converter; import org.apache.fesod.sheet.enums.CellDataTypeEnum; import org.apache.fesod.sheet.metadata.GlobalConfiguration; @@ -48,9 +50,11 @@ public CellDataTypeEnum supportExcelTypeKey() { @Override public Date convertToJavaData( ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - java.util.Date date = DateUtils.getJavaDate( - cellData.getNumberValue().doubleValue(), DateUtils.isDate1904(contentProperty, globalConfiguration)); - return new Date(date.getTime()); + LocalDate localDate = DateUtils.getLocalDate( + cellData.getNumberValue().doubleValue(), + DateUtils.isDate1904(contentProperty, globalConfiguration)); + + return localDate == null ? null : Date.valueOf(localDate); } @Override