From 6ff6fbff13fc5b1a79d600af5261145bcd51de01 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Wed, 8 Feb 2023 19:20:53 +0800 Subject: [PATCH] =?UTF-8?q?*=20=E5=85=BC=E5=AE=B9`LocalDate`=20[Issue=20#2?= =?UTF-8?q?908](https://github.com/alibaba/easyexcel/issues/2908)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../converters/DefaultConverterLoader.java | 10 ++- .../localdate/LocalDateDateConverter.java | 36 +++++++++ .../localdate/LocalDateNumberConverter.java | 57 ++++++++++++++ .../localdate/LocalDateStringConverter.java | 52 +++++++++++++ .../LocalDateTimeDateConverter.java | 4 +- ...java => LocalDateTimeNumberConverter.java} | 2 +- .../com/alibaba/excel/util/DateUtils.java | 74 +++++++++++++++++++ .../core/converter/ConverterDataListener.java | 11 ++- .../core/converter/ConverterDataTest.java | 8 +- .../core/converter/ConverterReadData.java | 3 + .../core/converter/ConverterWriteData.java | 3 + .../alibaba/easyexcel/test/util/TestUtil.java | 36 +++++++++ pom.xml | 2 +- update.md | 4 + 15 files changed, 290 insertions(+), 14 deletions(-) create mode 100644 easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateDateConverter.java create mode 100644 easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateNumberConverter.java create mode 100644 easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateStringConverter.java rename easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/{LocalDateNumberConverter.java => LocalDateTimeNumberConverter.java} (96%) create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/util/TestUtil.java diff --git a/README.md b/README.md index 7987c16c..c6b92caa 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析 com.alibaba easyexcel - 3.2.0 + 3.2.1 ``` diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java index ac2dd8dc..1b04d240 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java @@ -31,7 +31,10 @@ import com.alibaba.excel.converters.inputstream.InputStreamImageConverter; import com.alibaba.excel.converters.integer.IntegerBooleanConverter; import com.alibaba.excel.converters.integer.IntegerNumberConverter; import com.alibaba.excel.converters.integer.IntegerStringConverter; -import com.alibaba.excel.converters.localdatetime.LocalDateNumberConverter; +import com.alibaba.excel.converters.localdate.LocalDateDateConverter; +import com.alibaba.excel.converters.localdate.LocalDateNumberConverter; +import com.alibaba.excel.converters.localdate.LocalDateStringConverter; +import com.alibaba.excel.converters.localdatetime.LocalDateTimeNumberConverter; import com.alibaba.excel.converters.localdatetime.LocalDateTimeDateConverter; import com.alibaba.excel.converters.localdatetime.LocalDateTimeStringConverter; import com.alibaba.excel.converters.longconverter.LongBooleanConverter; @@ -83,6 +86,9 @@ public class DefaultConverterLoader { putAllConverter(new DateStringConverter()); putAllConverter(new LocalDateNumberConverter()); + putAllConverter(new LocalDateStringConverter()); + + putAllConverter(new LocalDateTimeNumberConverter()); putAllConverter(new LocalDateTimeStringConverter()); putAllConverter(new DoubleBooleanConverter()); @@ -121,6 +127,7 @@ public class DefaultConverterLoader { putWriteConverter(new ByteNumberConverter()); putWriteConverter(new DateDateConverter()); putWriteConverter(new LocalDateTimeDateConverter()); + putWriteConverter(new LocalDateDateConverter()); putWriteConverter(new DoubleNumberConverter()); putWriteConverter(new FloatNumberConverter()); putWriteConverter(new IntegerNumberConverter()); @@ -139,6 +146,7 @@ public class DefaultConverterLoader { putWriteStringConverter(new BooleanStringConverter()); putWriteStringConverter(new ByteStringConverter()); putWriteStringConverter(new DateStringConverter()); + putWriteStringConverter(new LocalDateStringConverter()); putWriteStringConverter(new LocalDateTimeStringConverter()); putWriteStringConverter(new DoubleStringConverter()); putWriteStringConverter(new FloatStringConverter()); diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateDateConverter.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateDateConverter.java new file mode 100644 index 00000000..3663476a --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateDateConverter.java @@ -0,0 +1,36 @@ +package com.alibaba.excel.converters.localdate; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.DateUtils; +import com.alibaba.excel.util.WorkBookUtil; + +/** + * LocalDate and date converter + * + * @author Jiaju Zhuang + */ +public class LocalDateDateConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return LocalDate.class; + } + + @Override + public WriteCellData convertToExcelData(LocalDate value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + LocalDateTime localDateTime = value == null ? null : value.atTime(0, 0); + WriteCellData cellData = new WriteCellData<>(localDateTime); + String format = null; + if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) { + format = contentProperty.getDateTimeFormatProperty().getFormat(); + } + WorkBookUtil.fillDataFormat(cellData, format, DateUtils.defaultLocalDateFormat); + return cellData; + } +} diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateNumberConverter.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateNumberConverter.java new file mode 100644 index 00000000..fbec7a4f --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateNumberConverter.java @@ -0,0 +1,57 @@ +package com.alibaba.excel.converters.localdate; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.DateUtils; + +import org.apache.poi.ss.usermodel.DateUtil; + +/** + * LocalDate and number converter + * + * @author Jiaju Zhuang + */ +public class LocalDateNumberConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return LocalDate.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.NUMBER; + } + + @Override + public LocalDate convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return DateUtils.getLocalDate(cellData.getNumberValue().doubleValue(), + globalConfiguration.getUse1904windowing()); + } else { + return DateUtils.getLocalDate(cellData.getNumberValue().doubleValue(), + contentProperty.getDateTimeFormatProperty().getUse1904windowing()); + } + } + + @Override + public WriteCellData convertToExcelData(LocalDate value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return new WriteCellData<>( + BigDecimal.valueOf(DateUtil.getExcelDate(value, globalConfiguration.getUse1904windowing()))); + } else { + return new WriteCellData<>(BigDecimal.valueOf( + DateUtil.getExcelDate(value, contentProperty.getDateTimeFormatProperty().getUse1904windowing()))); + } + } +} diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateStringConverter.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateStringConverter.java new file mode 100644 index 00000000..68e3e0b0 --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateStringConverter.java @@ -0,0 +1,52 @@ +package com.alibaba.excel.converters.localdate; + +import java.text.ParseException; +import java.time.LocalDate; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.DateUtils; + +/** + * LocalDate and string converter + * + * @author Jiaju Zhuang + */ +public class LocalDateStringConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return LocalDate.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalDate convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws ParseException { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return DateUtils.parseLocalDate(cellData.getStringValue(), null, globalConfiguration.getLocale()); + } else { + return DateUtils.parseLocalDate(cellData.getStringValue(), + contentProperty.getDateTimeFormatProperty().getFormat(), globalConfiguration.getLocale()); + } + } + + @Override + public WriteCellData convertToExcelData(LocalDate value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return new WriteCellData<>(DateUtils.format(value, null, globalConfiguration.getLocale())); + } else { + return new WriteCellData<>( + DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat(), + globalConfiguration.getLocale())); + } + } +} diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java index 072a7864..39276df9 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java @@ -10,13 +10,13 @@ import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.WorkBookUtil; /** - * Date and date converter + * LocalDateTime and date converter * * @author Jiaju Zhuang */ public class LocalDateTimeDateConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return LocalDateTime.class; } diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateNumberConverter.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeNumberConverter.java similarity index 96% rename from easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateNumberConverter.java rename to easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeNumberConverter.java index 4542fd08..51959fde 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateNumberConverter.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeNumberConverter.java @@ -18,7 +18,7 @@ import org.apache.poi.ss.usermodel.DateUtil; * * @author Jiaju Zhuang */ -public class LocalDateNumberConverter implements Converter { +public class LocalDateTimeNumberConverter implements Converter { @Override public Class supportJavaTypeKey() { diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/util/DateUtils.java b/easyexcel-core/src/main/java/com/alibaba/excel/util/DateUtils.java index fb19a105..cab7e4d0 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/util/DateUtils.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/util/DateUtils.java @@ -4,7 +4,9 @@ import java.math.BigDecimal; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Date; @@ -59,6 +61,8 @@ public class DateUtils { public static String defaultDateFormat = DATE_FORMAT_19; + public static String defaultLocalDateFormat = DATE_FORMAT_10; + private DateUtils() {} /** @@ -95,6 +99,25 @@ public class DateUtils { } } + /** + * convert string to date + * + * @param dateString + * @param dateFormat + * @param local + * @return + */ + public static LocalDate parseLocalDate(String dateString, String dateFormat, Locale local) { + if (StringUtils.isEmpty(dateFormat)) { + dateFormat = switchDateFormat(dateString); + } + if (local == null) { + return LocalDate.parse(dateString, DateTimeFormatter.ofPattern(dateFormat)); + } else { + return LocalDate.parse(dateString, DateTimeFormatter.ofPattern(dateFormat, local)); + } + } + /** * convert string to date * @@ -188,6 +211,38 @@ public class DateUtils { } } + /** + * Format date + * + * @param date + * @param dateFormat + * @return + */ + public static String format(LocalDate date, String dateFormat) { + return format(date, dateFormat, null); + } + + /** + * Format date + * + * @param date + * @param dateFormat + * @return + */ + public static String format(LocalDate date, String dateFormat, Locale local) { + if (date == null) { + return null; + } + if (StringUtils.isEmpty(dateFormat)) { + dateFormat = defaultLocalDateFormat; + } + if (local == null) { + return date.format(DateTimeFormatter.ofPattern(dateFormat)); + } else { + return date.format(DateTimeFormatter.ofPattern(dateFormat, local)); + } + } + /** * Format date * @@ -271,6 +326,25 @@ public class DateUtils { return DateUtil.getLocalDateTime(date, use1904windowing, true); } + /** + * Given an Excel date with either 1900 or 1904 date windowing, + * converts it to a java.time.LocalDate. + * + * Excel Dates and Times are stored without any timezone + * information. If you know (through other means) that your file + * uses a different TimeZone to the system default, you can use + * this version of the getJavaDate() method to handle it. + * + * @param date The Excel date. + * @param use1904windowing true if date uses 1904 windowing, + * or false if using 1900 date windowing. + * @return Java representation of the date, or null if date is not a valid Excel date + */ + public static LocalDate getLocalDate(double date, boolean use1904windowing) { + LocalDateTime localDateTime = getLocalDateTime(date, use1904windowing); + return localDateTime == null ? null : localDateTime.toLocalDate(); + } + /** * Determine if it is a date format. * diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java index fc353ba2..68a585fc 100644 --- a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java @@ -3,9 +3,11 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; import java.math.BigInteger; import java.text.ParseException; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import com.alibaba.easyexcel.test.util.TestUtil; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelCommonException; @@ -32,12 +34,9 @@ public class ConverterDataListener extends AnalysisEventListener data() throws Exception { List list = new ArrayList(); ConverterWriteData converterWriteData = new ConverterWriteData(); - converterWriteData.setDate(DateUtils.parseDate("2020-01-01 01:01:01")); - converterWriteData.setLocalDateTime(DateUtils.parseLocalDateTime("2020-01-01 01:01:01", null, null)); + converterWriteData.setDate(TestUtil.TEST_DATE); + converterWriteData.setLocalDate(TestUtil.TEST_LOCAL_DATE); + converterWriteData.setLocalDateTime(TestUtil.TEST_LOCAL_DATE_TIME); converterWriteData.setBooleanData(Boolean.TRUE); converterWriteData.setBigDecimal(BigDecimal.ONE); converterWriteData.setBigInteger(BigInteger.ONE); diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java index f9a6bee6..1ee3aea9 100644 --- a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java @@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; import java.math.BigInteger; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Date; @@ -22,6 +23,8 @@ public class ConverterReadData { @ExcelProperty("日期") private Date date; @ExcelProperty("本地日期") + private LocalDate localDate; + @ExcelProperty("本地日期时间") private LocalDateTime localDateTime; @ExcelProperty("布尔") private Boolean booleanData; diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java index 6782aa1a..88d7b765 100644 --- a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java @@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; import java.math.BigInteger; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Date; @@ -22,6 +23,8 @@ public class ConverterWriteData { @ExcelProperty("日期") private Date date; @ExcelProperty("本地日期") + private LocalDate localDate; + @ExcelProperty("本地日期时间") private LocalDateTime localDateTime; @ExcelProperty("布尔") private Boolean booleanData; diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/util/TestUtil.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/util/TestUtil.java new file mode 100644 index 00000000..8246f5b9 --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/util/TestUtil.java @@ -0,0 +1,36 @@ +package com.alibaba.easyexcel.test.util; + +import java.io.File; +import java.io.InputStream; +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Date; + +import com.alibaba.excel.util.DateUtils; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; + +/** + * test util + * + * @author Jiaju Zhuang + */ +@Slf4j +public class TestUtil { + + public static final Date TEST_DATE; + public static final LocalDate TEST_LOCAL_DATE = LocalDate.of(2020, 1, 1); + public static final LocalDateTime TEST_LOCAL_DATE_TIME = LocalDateTime.of(2020, 1, 1, 1, 1, 1); + + static { + try { + TEST_DATE = DateUtils.parseDate("2020-01-01 01:01:01"); + } catch (ParseException e) { + log.error("init TestUtil error.", e); + throw new RuntimeException(e); + } + } + +} diff --git a/pom.xml b/pom.xml index 70153a8e..3466d01e 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ - 3.2.0 + 3.2.1 UTF-8 1.8 true diff --git a/update.md b/update.md index 36c98000..54c01471 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,7 @@ +# 3.2.1 + +* 兼容`LocalDate` [Issue #2908](https://github.com/alibaba/easyexcel/issues/2908) + # 3.2.0 * 修复部分xlsx读取日期可能相差1秒的bug [Issue #1956](https://github.com/alibaba/easyexcel/issues/1956)