From 28556134ff95756cfe9c448eb53c0c61f9542aa9 Mon Sep 17 00:00:00 2001 From: ywzou Date: Sat, 28 Jan 2023 21:20:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9ALocalDate=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + .../converters/DefaultConverterLoader.java | 12 +- .../localdate/LocalDateConverter.java | 34 ++++++ .../localdate/LocalDateNumberConverter.java | 50 ++++++++ .../localdate/LocalDateStringConverter.java | 47 ++++++++ ...java => LocalDateTimeNumberConverter.java} | 2 +- .../excel/metadata/data/WriteCellData.java | 19 ++- .../com/alibaba/excel/util/DateUtils.java | 48 ++++++++ .../executor/AbstractExcelWriteExecutor.java | 42 +++++-- .../test/core/localdate/DataEntry.java | 114 ++++++++++++++++++ .../test/core/localdate/EntryListener.java | 41 +++++++ .../test/core/localdate/LocalDateTest.java | 99 +++++++++++++++ .../localdate/local-date-time-fill.xlsx | Bin 0 -> 10262 bytes .../resources/localdate/local-date-time.xlsx | Bin 0 -> 10727 bytes .../resources/localdate/local-date-time2.xlsx | Bin 0 -> 11061 bytes 15 files changed, 490 insertions(+), 20 deletions(-) create mode 100644 easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateConverter.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/core/localdate/DataEntry.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/EntryListener.java create mode 100644 easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/LocalDateTest.java create mode 100644 easyexcel-test/src/test/resources/localdate/local-date-time-fill.xlsx create mode 100644 easyexcel-test/src/test/resources/localdate/local-date-time.xlsx create mode 100644 easyexcel-test/src/test/resources/localdate/local-date-time2.xlsx diff --git a/.gitignore b/.gitignore index 93472b7d..16cbd45d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ antx.properties output/ .flattened-pom.xml dependency-reduced-pom.xml +.settings/ +*.factorypath 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..af82074c 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,8 +31,11 @@ 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.LocalDateConverter; +import com.alibaba.excel.converters.localdate.LocalDateNumberConverter; +import com.alibaba.excel.converters.localdate.LocalDateStringConverter; import com.alibaba.excel.converters.localdatetime.LocalDateTimeDateConverter; +import com.alibaba.excel.converters.localdatetime.LocalDateTimeNumberConverter; import com.alibaba.excel.converters.localdatetime.LocalDateTimeStringConverter; import com.alibaba.excel.converters.longconverter.LongBooleanConverter; import com.alibaba.excel.converters.longconverter.LongNumberConverter; @@ -82,8 +85,11 @@ public class DefaultConverterLoader { putAllConverter(new DateNumberConverter()); putAllConverter(new DateStringConverter()); - putAllConverter(new LocalDateNumberConverter()); + putAllConverter(new LocalDateTimeNumberConverter()); putAllConverter(new LocalDateTimeStringConverter()); + + putAllConverter(new LocalDateNumberConverter()); + putAllConverter(new LocalDateStringConverter()); putAllConverter(new DoubleBooleanConverter()); putAllConverter(new DoubleNumberConverter()); @@ -120,6 +126,7 @@ public class DefaultConverterLoader { putWriteConverter(new BooleanBooleanConverter()); putWriteConverter(new ByteNumberConverter()); putWriteConverter(new DateDateConverter()); + putWriteConverter(new LocalDateConverter()); putWriteConverter(new LocalDateTimeDateConverter()); putWriteConverter(new DoubleNumberConverter()); putWriteConverter(new FloatNumberConverter()); @@ -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/LocalDateConverter.java b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateConverter.java new file mode 100644 index 00000000..001d4961 --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateConverter.java @@ -0,0 +1,34 @@ +package com.alibaba.excel.converters.localdate; + +import java.time.LocalDate; + +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 converter + * + * @author ywzou + */ +public class LocalDateConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return LocalDate.class; + } + + @Override + public WriteCellData convertToExcelData(LocalDate 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.DATE_FORMAT_10); + 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..8bd6a24e --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateNumberConverter.java @@ -0,0 +1,50 @@ +package com.alibaba.excel.converters.localdate; + +import java.math.BigDecimal; +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; + +import org.apache.poi.ss.usermodel.DateUtil; + +/** + * LocalDate and number converter + * + * @author ywzou + */ +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..ab2bbb53 --- /dev/null +++ b/easyexcel-core/src/main/java/com/alibaba/excel/converters/localdate/LocalDateStringConverter.java @@ -0,0 +1,47 @@ +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 ywzou + */ +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/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/metadata/data/WriteCellData.java b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java index f8ce9064..ef0c389c 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java @@ -1,11 +1,13 @@ package com.alibaba.excel.metadata.data; import java.math.BigDecimal; +import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.ZoneId; import java.util.Date; import java.util.List; +import org.apache.poi.ss.usermodel.CellStyle; + import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.util.ListUtils; import com.alibaba.excel.write.metadata.style.WriteCellStyle; @@ -14,7 +16,6 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.apache.poi.ss.usermodel.CellStyle; /** * wirte cell data @@ -29,7 +30,7 @@ public class WriteCellData extends CellData { /** * Support only when writing.{@link CellDataTypeEnum#DATE} */ - private LocalDateTime dateValue; + private Object dateValue; /** * rich text.{@link CellDataTypeEnum#RICH_TEXT_STRING} @@ -105,8 +106,18 @@ public class WriteCellData extends CellData { throw new IllegalArgumentException("DateValue can not be null"); } setType(CellDataTypeEnum.DATE); - this.dateValue = LocalDateTime.ofInstant(dateValue.toInstant(), ZoneId.systemDefault()); + // this.dateValue = LocalDateTime.ofInstant(dateValue.toInstant(), ZoneId.systemDefault()); + this.dateValue = dateValue; } + + public WriteCellData(LocalDate dateValue) { + super(); + if (dateValue == null) { + throw new IllegalArgumentException("DateValue can not be null"); + } + setType(CellDataTypeEnum.DATE); + this.dateValue = dateValue; + } public WriteCellData(LocalDateTime dateValue) { super(); 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..786ce023 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,6 +4,7 @@ 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.ZoneId; import java.time.format.DateTimeFormatter; @@ -95,6 +96,26 @@ public class DateUtils { } } + /** + * convert string to LocalDate + * + * @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 * @@ -198,6 +219,29 @@ public class DateUtils { public static String format(LocalDateTime 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 = DATE_FORMAT_10; + } + + if (local == null) { + return date.format(DateTimeFormatter.ofPattern(dateFormat)); + } else { + return date.format(DateTimeFormatter.ofPattern(dateFormat, local)); + } + } /** * Format date @@ -271,6 +315,10 @@ public class DateUtils { return DateUtil.getLocalDateTime(date, use1904windowing, true); } + public static LocalDate getLocalDate(double date, boolean use1904windowing) { + return getLocalDateTime(date, use1904windowing).toLocalDate(); + } + /** * Determine if it is a date format. * diff --git a/easyexcel-core/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java b/easyexcel-core/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java index 7f8fe0ea..ee4e85af 100644 --- a/easyexcel-core/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java +++ b/easyexcel-core/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java @@ -1,7 +1,22 @@ package com.alibaba.excel.write.executor; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Date; import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; + import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; @@ -24,18 +39,6 @@ import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WriteHandlerUtils; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Hyperlink; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFClientAnchor; - /** * Excel write Executor * @@ -92,7 +95,20 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { cell.setCellValue(cellData.getNumberValue().doubleValue()); return; case DATE: - cell.setCellValue(cellData.getDateValue()); + // cell.setCellValue(cellData.getDateValue()); + + Object dateValue = cellData.getDateValue(); + if (dateValue instanceof Date) { + cell.setCellValue((Date) dateValue); + } + + if (dateValue instanceof LocalDate) { + cell.setCellValue((LocalDate) dateValue); + } + + if (dateValue instanceof LocalDateTime) { + cell.setCellValue((LocalDateTime) dateValue); + } return; case RICH_TEXT_STRING: cell.setCellValue(StyleUtil diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/DataEntry.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/DataEntry.java new file mode 100644 index 00000000..c42182aa --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/DataEntry.java @@ -0,0 +1,114 @@ +package com.alibaba.easyexcel.test.core.localdate; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Date; + +import com.alibaba.fastjson.annotation.JSONField; + +/** + * @author ywzou + */ +public class DataEntry { + private String userName; + private int age; + private boolean hashChild; + private BigDecimal income; + private double height; + private Double weight; + +// @DateTimeFormat(value = "yyyy-MM-dd") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime birthdayTime;// yyyy-MM-dd HH:mm:ss + + @JSONField(format = "yyyy-MM-dd") + private LocalDate birthday;// yyyy-MM-dd + + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private Date createDate;// yyyy-MM-dd HH:mm:ss + +// @DateTimeFormat(value = "yyyy-MM-dd") + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + private Date modifyDate;// yyyy-MM-dd HH:mm:ss + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public boolean isHashChild() { + return hashChild; + } + + public void setHashChild(boolean hashChild) { + this.hashChild = hashChild; + } + + public BigDecimal getIncome() { + return income; + } + + public void setIncome(BigDecimal income) { + this.income = income; + } + + public double getHeight() { + return height; + } + + public void setHeight(double height) { + this.height = height; + } + + public Double getWeight() { + return weight; + } + + public void setWeight(Double weight) { + this.weight = weight; + } + + public LocalDateTime getBirthdayTime() { + return birthdayTime; + } + + public void setBirthdayTime(LocalDateTime birthdayTime) { + this.birthdayTime = birthdayTime; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public Date getModifyDate() { + return modifyDate; + } + + public void setModifyDate(Date modifyDate) { + this.modifyDate = modifyDate; + } +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/EntryListener.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/EntryListener.java new file mode 100644 index 00000000..ee977792 --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/EntryListener.java @@ -0,0 +1,41 @@ +package com.alibaba.easyexcel.test.core.localdate; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.alibaba.fastjson.JSONObject; + +/** + * 读的监听器 + * + * @author ywzou + * + */ +public class EntryListener implements ReadListener { + + private static final Logger log = LoggerFactory.getLogger(EntryListener.class); + + private List entries = new ArrayList<>(); + + // 这个每一条数据解析都会来调用 + @Override + public void invoke(DataEntry data, AnalysisContext context) { + log.info("解析到一条数据:{}", JSONObject.toJSONString(data)); + entries.add(data); + } + + // 所有数据解析完成了 都会来调用 + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + + public List getEntries() { + return entries; + } +} diff --git a/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/LocalDateTest.java b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/LocalDateTest.java new file mode 100644 index 00000000..e3568ee7 --- /dev/null +++ b/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/core/localdate/LocalDateTest.java @@ -0,0 +1,99 @@ +package com.alibaba.easyexcel.test.core.localdate; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.fastjson2.JSON; + +/** + * @author Jiaju Zhuang + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class LocalDateTest { + + private static final Logger log = LoggerFactory.getLogger(LocalDateTest.class); + + // 读取 + @Test + public void read() throws Exception { + String fileName = TestFileUtil.getPath() + "localdate/local-date-time.xlsx"; + EntryListener entryListener = new EntryListener(); + EasyExcel.read(fileName, DataEntry.class, entryListener).sheet().doRead(); + log.info("读取到的数据==>{}", JSON.toJSONString(entryListener.getEntries())); + } + + // 读取 + @Test + public void read2() throws Exception { + String fileName = TestFileUtil.getPath() + "localdate/local-date-time2.xlsx"; + EntryListener entryListener = new EntryListener(); + EasyExcel.read(fileName, DataEntry.class, entryListener).sheet().doRead(); + log.info("读取到的数据==>{}", JSON.toJSONString(entryListener.getEntries())); + } + + // 写 + @Test + public void write() throws Exception { + + List entries = buildData(); + + String fileName = TestFileUtil.getPath() + "local-date-time-" + System.currentTimeMillis() + ".xlsx"; + + EasyExcel.write(fileName, DataEntry.class).sheet("demo").doWrite(entries); + } + + // 填充 + @Test + public void fill() throws Exception { + List entries = buildData(); + String templateFileName = TestFileUtil.getPath() + "localdate/local-date-time-fill.xlsx"; + + String fileName = TestFileUtil.getPath() + "local-date-time-fill-" + System.currentTimeMillis() + ".xlsx"; + + EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(entries); + } + + private List buildData() { + List entries = ListUtils.newArrayList(); + BigDecimal hundred = new BigDecimal(1000); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDate localDate = LocalDate.now(); + Date date = new Date(); + Calendar calendar = Calendar.getInstance(); + for (int i = 1; i < 11; i++) { + calendar.setTime(date); + + DataEntry item = new DataEntry(); + item.setUserName("王麻子" + i); + item.setAge(i * 10); + item.setHashChild(i % 2 > 0); + item.setIncome(hundred.multiply(new BigDecimal(i))); + item.setHeight(i % 2 > 0 ? 1.72 : 1.68); + item.setWeight(i % 2 > 0 ? 50.00 : 40.00); + item.setBirthdayTime(localDateTime.plusDays(i)); + item.setBirthday(localDate.plusDays(i)); + + calendar.add(Calendar.DAY_OF_MONTH, i); + item.setCreateDate(calendar.getTime()); + + calendar.add(Calendar.HOUR_OF_DAY, i); + item.setModifyDate(calendar.getTime()); + entries.add(item); + } + return entries; + } + +} diff --git a/easyexcel-test/src/test/resources/localdate/local-date-time-fill.xlsx b/easyexcel-test/src/test/resources/localdate/local-date-time-fill.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4caec8787cd63a34107085d6f1ee6f70952ec173 GIT binary patch literal 10262 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 literal 0 HcmV?d00001 diff --git a/easyexcel-test/src/test/resources/localdate/local-date-time.xlsx b/easyexcel-test/src/test/resources/localdate/local-date-time.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8c424fac2fdb34d64ea5c199dea7fa09fb77594a GIT binary patch literal 10727 zcmeHN1y@|j)@_^)?lcfAxHaw?2=49{+@Wy|1PBC|B)B_)-~{lfv z$Rv#hwiIDw z`f7Qdo6(Ix&`4~gMwZe65{hX(4_Ij2#X2E@l)-KQ4^K3C2o4CY6Vao`d3j^fW&rOzObFu2 z`A<>d15tOxU97&HMUq^W&Z5t!=ZKLly*)%HzJrdl`+GQm@?VB&tp@9p6DarOp-)ku z!_>&d+ztX}`T769;rU-YCjaBp-^VK`wX>pz?n~di>OP;CkHvf{=OHHji9+4~h0GjA zZB#B5@q7y{38p&HOE{^3CjXn>*?GaJt!|3570&k&*th~u>O9Iq-(5MoAu-Unyp?o* zzubZ4K5;s6mMkUfMd#iW!%+IMC|j;)@rmTvp+qI-5Q`QO5GS7`6kjMgP`6V-XTkKM z9A@IF+HP5BMLkc}R>Dwfz|`ApAeu)VbVpeHDTtY`r` zWBq-Qu!Kr~EPxIWW<&r01L_%1JFthNi>;}nqwUXmEKl9QafTJwFSF*}_)AP_a60AK`t2+-Dfc&QZ#IRXo8?J%@v}jqP_4wWFmCs*Lb}kZ@-Ud(dUG323O8 zPmLPfTBXcih+p8nnW_p&Nr{A{%C+FYXJ@LZEFn^i?zbsNgc$qgXumoB!cCqcXA{`m zBVnyulh%a9Qs}MmhE&Z9hzX$xnV-xeTw_XMLCN3L51J(&l_ExSL?#1fZPw5RZhkM) zXDy4={l@X)jChpxE}@n7I~{!L7~yA(;&t0QDt+|x_pTRWn#-h&f-mBh#;oA;G;FDZ zmi#cwTGl7qaw9@wZ<^y+a?CFiez2%vKaq)Qk_lO}jvO*6nY^(Q(^_+*rqUL;HL-kg zJ7PFkPn7Q~#%R4S+RZGeE=h`cu(g;4AJ{t*iQ+~ujxz{Iyz`M@tD;JbS4 z6mgTl=2k5$`iPCWIn~r`**-$rk@tCa&))fV7Ed3ctsb!+F&3W3K7{yH~eZDrG@)IF52f2VYyaN@gT=#xe$t%(50Fi=YW z5&Hj=*#DXaV4x}uIxzmbulK47ave~Wf^zqY)g#p%4{O>LOu3`6je*=#LqAJH!Qp?h zNX*b^pgk!EhI0({+8^k0Kj%VUfx|g%V=Q`&4eyO(w=aO;IB+}whitlAMj9lAfP=lW zwOzW4f}R4wX%LR@X3D_j{c%A@4SJPZKq+z3FdE8fGsx=3ZUY&9+zSnZeKp@-Tm`G` zlm*q)*ORBvTddtTh|iuOW(IkYjU0o3GJ@T}Mz3!!NnLT3aJK4AR-qSU)2<_>=Q|9tz z`IIwM&40lM00^OP{22uyR_5le5b&=X+s|;AmM9l9OODyK|K{p3<~d=)fS$9aMrqOP zSjlV`Xw^9qwiDq6gd7lb|&jS>X66e#wH_ z$$HGGv1B+#4oh$ym)QxPpr5|qO@*L#{VAR(xpa}AWGQ9}!gE7S<6tE_IIi-GG_^Y2PS~sbrKQD48O%!*t5_K2V71XnONZUM`HNsRdP={! zVagCx8;ne`?MUIF%8q*pERr0+Hr_(?kj=LC$WSz{^6PZ;#ocAbA_Y8U_e9h#W-;BU z*-C23+Dtsn1YUQCVoG&TI(7ACQap*TcIjk1cEfR7%Hq5?YE6BYzJ$*X#{AUbilSY7dRo7kKP$94d?uAI)2H=dgRj}cSzr3=C|Aj|m9}GUuA=yuY{9;LB z(uhMYE9SER>J>QbR^#^961wp;UjyRG7*2~n+2ri)gF9h{<_`H+@^w!$KsCasb+hxr z3yb@O+qd2u&HnfEzPr_wvvYU)B95yq{8jhR#G_Oq_fxvDx<4 z(~?~CDrZm&K22Jv)WXn$3FR^x>z7TA8G;8B&{*krCudbA0m%??Xw1K~x54|rn&hm;o-9Zl>y{t4#$iFkIq2Dg zR@gdqB)z@L(e|@CDGSQeg9wb5;eSBn7b^;q-&BA^$G@;5VVQ3}3kAoE|1Gt$l%ydcq<0yi)1H zi7opWiUHFc1hBuiwxG6~>DCGKOHZi*61)U{>%9Uw)1angJpi#L(W(A&Lz|iQSikH? zm7zgJ`D#Yu@z{pJuxV`QRnL($zZBw$MDsNV44f# ztk!>Px#Q9&qvEMvhb6p#G&3Y-6YJ=88&MdaSDu*MoAH%QyqZ?$Kfs#z=km2E0q~bd z|7JO7wAdr)67|^!>>mJ4EUf&^P7Q*fVH^nodqge{d8ubgjtmy(i$*u+w&7{R8!oCm zPE~d16^NFOVi@5VX&FU0&Os%`)RCU3{HiH)Xh_Eu`gU#fQI%%TFKdaNEV);Gvcs~a z(&>jV`ZbqYX0wGlWH860g>{v?qNqHOEBX`uX&NYj?Gdi?_adr&H!|8U16J z4$N^4w}ZBPn*3+t`-E|Av|^ml7tb z`WmDpL#vGi`W&!}v2XCzhk*ttMxNO#GzT=z$M;#QN^50(t922ScQ79r0ng}(dwit6 z#4(&&;Zmk*orohp2FT}ysjau<;HTL5WO;vi=cv?jd%A? zDK%_dNUISQ%Q$Tbn{GM@G;X99Ax?P3Ac`u7VB{L~`V!bXRsQzSkfmcBT}RHr%-^L! z-`HD~1M>Rv&|;J|@{6QL?jj&*rV}l-y|bcn#1i1i9{9$h?jwI{t$)&UX63VyT%Tc* z@ly1KQKQAG2I5U4BuCNYJ0}zoqSLkr^o1AfzBM5+-n$E}6ON*w=E@L9&Bm7%n;Se? zNh2p_CpSoMoFB;WAgOtoZRno+(!N3P4OH82jJBN{y;=fiT% z=5IqACen^27|IX|xH&!US`@thp0FNs|7OTuozLZ(H+|Mc;aoXm_&UysId=6 zJFCmzg=sObttW|8AY2`JcMN`|>Ij6K?d}WlBs=9jF7p;u zG@!CW=@;yb0Yc_HAA|7}eHprVP3qb)Dqj0Zl9qLJbfV=4Ne=;6t$3+bugn}!v_IgT zq_(o&RghI_tWbvJ&RA4qtQoGJpHgltbQ^X$&vCz1%>oX?jF&FnwH@Jb0Ny zkQ#pey7jqO445R7KyooGP~$8dT`Rs zwwb>Bp@->4>$aSDth#B>%~u&%Pp2Lj3pOmAdz;lRySL0z=3%;%W^ko*b?io+cF{CQ z`qJ-mN#UHjJC^4yjA?-VVk8@ch7Q{zGQ0I)ggK0N84Q)1HXUyb8Td>60i~|A6($wr>I&I*kYjU;S z`)O3$f{iBG-_`b;Gq3twd(+m+t2B$6tGRl~57ACfA0?}FMvuRagR^cF#$K>0ctXgz zOE;D z#?JSB?ERQd*;cv5kEh`pY=+_7tHb%KpvDoVMi1iC0y2IcgUMPL-7|&A3K~dMkx!&m zITFRA7PDZT=@9LaGwqSlt*LBXDd*KktoAr~o@9t=E@{8q?wypKTgZbM~`8yBTbVT>0Zzn^hNgRx5 zWX*{0?32tX@`#K1@^CiR9IFEJL&YQQCx|e=>`#8=9`4;A;6-jE zHe*kX3$JQ-h_X_$jA=apX?eDAtvF&##`^-7gqMGVYqoIOs6&Zazj|>y zQMgwcW3$T_!5P6ZW`gHubJcS)|M=*w##f3h?Kdj*UWIQFrfR43k;1oxs12RBnmYrH zlQrdkBo#0(6qpQ5Ul!TUAmGElr6m%$spEU{Im2@{f$aOBWtlMfq+7m>F9hPSXmh-Z zBuWbRQAD4eT7hnPP}i95stOtvxs4+P)xDySGlx}&6%SOXw?c1q$H5x9BNe!l?Xtyq zZrk||xD%!AMY^C9o0uhI6=&6`D!pqgeUl0ee-Fpb`n~;xQ|5s;K&9TfxuJJa%Rla# zb&uy4V+IC%%T&v9v4d;}bzjh74ogMN6d5?46Xm-%2{44bG%Ow8OZZaqO~Go*Wmzw#YX@D+8>iM#MR5r9P)GF^j@dRm{>-Oa=`_V0-dvf{ zI7uQ*RUYh!1@#>l)f`gIhEd*^-zvqJ)}L4)Y-3@sSQ4UTwv|;q7I>8GKvY#xTJD(c zv&X^ZqXLX3En-QI2cmy~jVzMa=={#zX0%w=#3q?f!Tv;FCS?hZ`7q*gJ##=7vUK7u zRV)Ue=!4&nq%UYTDiC0h_R4?6uq;(Kblx|g7Mj^Dcq-qAea$@AGriqsxeIJDVa;5Vb(aVg?RfN~ z`UuUNoJ2cVQ%FPKy2DJ8@zHqaARSiCx;? z88lojz+<1!S@Jg9dkE!riG#-Qr+sz!1D0t&5ZQ~T-7Oa-@ebzbo@XhnS4YN`#Rt#! z+A5tWec1@2e`8$zl78$h@iZ|4!iIkJ0oqk=WAw}1gCd4uJ00N?J%Qt)W==)1FxB46 zGPfV8H-v?l`Xxt(K3@*%YHdHwu}};RR7J})B@bn})~hN5&6R3Rig&wk>uUCL7+zVO z?M_VkgsxhGBsK29g!(Q_J0uaTTO@E^5i!y#2kk_ZCS!9uG!PG`lnTEus(N?NgGM`BisQzgC_d-`3ICFuU)|0>L2DaoxuzW zk%RUh`R)T|oiq^K#u?WWOoj0uSH0wJBU@;>-=2?Y>To!VB&OMBuZk1S0QA4#(tT1f zZ@(kd$~7?ZsOFg@q-y=g-UVCR{1r+{Wz&lyZe62FBy$pppiif^0#RS$YGHH&489-- z^32%2UD|iVpGue*;6LhYGu=T$;yj}{G+q1JzGhmhs}w}1eK-6m>gLs_uup%!rZZGF6`pHIn=o0h{On+~loeYSZcHFK9&XbiiA z_6|ArnF7f|Pj|cGV+uooy~%cv35z0d2vyq|j^c$q&CQ+#|2^?PMFdUhsZ(@la_tQ? z5r_L{M6fb(F*j3lb+LA^{1q5nN5vF7$Z-*un!-J-z6sQ5bd4xmuyy8_9s<5K(^DZZ z>}#ZRBoTsF5KaU;JyF;?*{ok7pxo^rc0UPQ%iXQ=LALr_s?FA?gIInR_h8w46E9j*KI0adp&oT`sV?q2IL4t^wQ|a%ep$4X?aT`(~jjcGI@AgZ@3LO%DJ5L ztdYK3eT7B*nwkPWH{-5y2+$|E zq$MWgrO}vYBv$7!#k*uAQr^>&w!FE4X5aswl@hRLmurLi?J3lUPyX=V&lKjLS*bsA zn!j^XzcQM^F>SBEu;M;Dhr1K^^huZuK^0fyq5P<^4rh8bgE;#x_8j-tr<%mPb#2XQ zXpKAdTCkYd0zHmtyb(6!`*Q-TiUXe+<`%I^-mN)YAhTes$rwv>3Y?;%Yk6xIHZF`($*!rQv7ufgr9iIXJ$phsmx8a|lU(bXG z0MP#70VgPRT+Ln7%w1i7atQpO%*JAB?XZ(LAiJuJ+jVb!Q#5GGgzR9!hO1=?l3VRk zlpEuJ(-~ZV$5Tzm{WOb)S|JVu68pj2ft0+)WN-zjcBdA8L43RTjdBo|enpa(C(TEA zuVMYi-A57>VRTFii5QnK!p!C2b1W+N{-W1OMaJX9G$+L^PCrh;M4bIgH!tHH#;(F{ z)n9vy-+GfA;k4uZSVU{}p`8Bfrz zytc5LU^Q{}X&EQ`%5_S!K^JjTYH!E3yyLd-50p8LrJ4yk%D!R1@wzvufHjGWe3~l8 zluS8y%d3v)Leg2QzSNyt-3C;zp;lNXO&;tKRL}3w7R)QV_NH4DMr}Xep4vT`3K1!_ z)QX%yw3QZ_P;2NlBC=X@R5?o&L0S+o%iLT=HXPMS+2J9*j(mw-si@T$;x!Az~K+P9!rSaOr(cH$>k)}3PKZSL?|f@7s!Z(l>SRS0 zB$ghK!Zn%bH_WvZ9E-x#s-pP#D>Lgj9M*1J8k%$ymj==jsyG5{UNvvD>CLK}aqw+* zwwk1(N~7d;`k8Z=-JrL#)4m-a;dW#6mJC7rdd%VMYCELfM!WY+6ID6R`7Jx#IK7(w zwLK3eQ^p>LAVWRv`y#iPyO~n#3k5aK(|0o#7xhcd23HwC!2_>R;af4U^tlD*^&)9$ zcAyLi%@{SGQV%EfyZzm{+&gX~Bh2f~dx{K$s4yhaku~8voUc6p$UoM`9M}jb|E{6@ z!~9SFnK(K9kA6^>{duLuEBvHi$hq_!#Zd-7La_20A%%YjtVBNkS!Z$$e)QvM@o^V? zZl>6eFpLgx*j>i)Veznx?i|OGLz$V(==k{xHpnBM?<$wc&4IkTkW~xNr<4qb-D;{F zmxihZvCg-c(}8nyn5#>S$X4VuX3M6XKf)%$j*HfnOL)nr<5Vw{8S=RMKY}0SE`Qtp zgiUg^%Q?SVA?n2UU2mc{)-5`h=-xKPXa3;p_GT5OF+F-|FHu>n13fqrUHA$%At3~j z(bEW5f(OQr0F}j@!LtPqr;Ldtu97J+iu~eSG%e8PDKR5X4lY-;&G3de_JGjWx`B9N zyzI6f?Xn;hbYQ8@c1m5HMhE$#QO1HHnJ{T40&P=jt$9GLQK|u-9YK+{ksT^OI`$;6 z5Rti~&-6X)9gN@(Ts`VzhgS*Wn*k%W=lKwS-b`W-;twUoBAUoXZDkl=&B|fFC!R8V zn-EP?v1sF_k%FvQ#0Ko%;HOwN@7-0A?4gaOCmL4p;M`nK^(sNT;tvS{1IrARTmO7m z?Oz@Culqk7T~n6(tAW2Bqxl!`=e-cR+WU_~H4lLgj~4uf_Cw{)gM$VS!GGPv{S5^G zGNDT0|KHMmXy@V1-fv5zDF1H6-}d<)T6vgw{%yqz>z9>>Y3PRr9xjf58^8zsGVpt; z{1Ez3MgNANQXrMGMrTJOo9-DHepWF+%Tveq}}nx-HF1&s-K0e}Ml0HgpBF5gjW2mk;Y1^~bSz(Hz>*;v~f zTiffscd<1F>M%N6S(0QzLsF*$Ai>Z7cl&=l0>$t9tvi{~TGaN1#9LK^GQJcR!VxwS zYLV~4#ydx;lh_AbTRCz~-n%VB6_9m)jF93KSBfXrbLM zguIO+a9<71}^PI%g`vueM<;H<}R)nqvXLtPrN!-Si&C*&2 zy?Z|2@yJk>bouE@rv{535s07!An1_2FQ+7kVL;RPQ0^N3(HYm+{nCa$8-(LCx=WJE z5_#s*;s*x|Kr>$ktTZ0IydVUYK<>hyU8r*5oZ|e9K?$GY=8i~S0K_?c!1-Frdx-?? zgLEinXEt{gN_bneh_alLDMGv!dxk>r2-dTwCn$izzo}`B3iIm=F!yA^cM-vAs%K|x z31njYI^jm_Od77FB%J)B6u>H`{>&X>CPS(0Af;;Sf|@tBtzq}uV4x#$^L zwu8iz+Atp68RU}tl*ri8Z&*hqdnwW{y)>)Y&jwRmy1C%Hiuz9beM5-zSHLUQe<}$R z$_7jkSV6d6005}qk#V+Ua4kxcdgi(I(@bJe@({C%%g4!>-3-9~Jmwo)F!>lL7fOAQUV>yHIEmE8Db7~Hd{ z0@;{B%%_GFXOGa(9Ak+bT9@FurM04t9r?JAIcmThRXBij^v2Qx?U_fHovs2fmsZ!; zIKy6qLH2Tj>)SRv8_!N{q$e(Pg`R@q1~%!qO@~5=zrK61y3XlDElHw`g->h$8)M#T z-xiqCbXOHMBIP$QXh2f`WzKY5EcygSnVdas-$erSjIaQ%fC%U@zvZ|3ygY?yvUFM4 zS4im(u@^y4XY9v<3pHpXuc(JJ`oSO zS`y{2*M{pq(cB}`R1q>?XQg0?nwl$1DCd_s!-+5C5YilT;3)Qo{)nsN=W&R7W!E}R zy@{wP`60b^eu>Vb^wNR+3{@Kf(?ML9*>;RnrW`ALb5H zFC&LO0|*qe3b$ZT=6`E~WlY!jgH3KY)&@83%U9EmorE0M{*2ERy(IJjNeS;m2ax7Q zb*17{X9m3j<5_X=h(#wSYmfr~MghnZ4wl|eLx+k{5YfZZDJ-P)Npu)EJoq@cmvM{_c(vLHMZ2Z7Pv z36_hrM~dngT3}czy7QPS67I96ZOS4pd(ZI*@jcW(@!Cf)CJqGVb0e7B_y9NvFt7i# z|9@xqzt#c>u&V~vj{o0VvC=!4Zm_F@`1pm{DajG*<-9!;*`dk-DqMdx%_1c!o9D$U z0d1p>`iu+{ludxk$#AdZH3!ND6vkx-U4Ae+v@3??2_KBjFlZPG&futo$X5~u1O0IS zpy&t@B@u|xAQ;t0pNh%7eM3!w_a!TrO#Gr@B7ogugxP`B0yy?+0Bj2ftABXk`6(Zk z_*U1|ktEWXY&|uIEndAy^K~H}2jRiL@yzBhU2GV-w_>kes) zutedxI(h7w6E^v23J6|83`<;P%_{e${ z$!{E)j8p0D6JbV-S%ve$OwV~(XTAJ(X9{;XALYZ11R(Z%@|YX(HBi5uI5^+$hi= zFs*xI&F}>2i>W*DkJkz;~ z_cjySJ2LHu7HCoNa;@!sEKYkDeTV{hl*ojdOM?LY2*24`zFmLXV}wI@q7zeE#EN~3h7L+j76v`BB7LU+fazNCTu#J4HE#1gsgW)Y}?@b46musPw z0eV*_@6rLOr`?18koam^P%=ldoA_9Mkt1aR9jNGkzy%@5%K7+(F@|x5rTBffHbTgC z#IzxqfDwEFQ;yaIbB191?Xp^M8KzmAI{gzxlXp)hqG%sx`xJ-|I;HWFe3|BLg9gkopSSV|ZZDYZ=duOqen`e+><%?Xs^k3^vx- zojuN}U50m05Mz494L11m+L!ahF-Z)CGkt0EggZ+-YhT;B{2B?dW9)7^Gew9Jc_#=a z90arET}b>8MmSPsz-MCeO#L*T7v!`G;P+TBn(~o(p$vK;Z4;8WkCbcS*>q&UIQrXD zwZr(q#!|WZY-QpR(I`ViFq7j_$QgPT=3*S!i8Aw2ZGL(q&39=De4i8EXY`qOM;|Iy zwvKf@ozmX#wITO@P7`Dqi3j~`ybWmt!XacP8xai%0+odv7iOdf7Q?iD~X&-hCZ*uzB-z>(~mGW2bL>dTiodp#;RzGE2Td{!?w*kmQ&$lK7GT(9cg zUw;fr9^183;6Q_gA(=umiaMma*0z`-(ES!|DqK*b6{=S{o?d;%4NY}YIM%~$fT`w44OFoI z-8F?QlSA*(fDFI1z2Alvhk zH|ITpzV69Vq7znHw-3gXe@mtQ60h0o2=zqgyBjSfya-9!fWQ*GK@PUtR%LQKbFA8p zZ}#bOXb3c&GbZT#{Tka?Qn_7;l6ee<>?9zE8=|Jpl#Q2kx5@PB_R&VZ?cs*)2C=kc z2bVRTT15#}HlBNe4NY=PKaWZ!ERt^C6f(tN2426BMu;H#3#~Ac42+(=Z}2Vrz-(#k znJ#1Z6pDt7wUMV?gSNh_5*sl1_RM60IkZ#4DQguFztDr6)YVg7F>VTQX7%}IQd`fP zRO1R#<1;d->vK5Zk6 z*IMCkquThnd~cU4J%0Sc2vH{p|MJnbhM+IB%7dx-m4B8AgPLwS2?6JPPG0=k`=fyx zXrVO&XaKU2`Z#96wC~U0wn*36+jf`)p%Wul4?J5Jz6<>5*8Tf1wGI zc=43wU7&bfA70}ihI)Fhryc!@tO23nzSJ77z1w?Kl|z6{2{UNjwcBCc1A=}NN>@+N z)>0t&yOQGQ5Z7im1d-i{tG4qiTjfz>7w2Z#oyY#~6Ftk{Z>G4Mi1XyUzYM~R(OniC z_I9&?P`U~_fl=uG7f$znXrudr*;8i+q$zNWx3U?iH2WX+9s1*m_=4WU9Zf=SRG#C( zWjMM6ory2GK_#xjaysOeh(r865%9nz=T}Tva_+Rf+#hPYP|JfoB#277yL*sxe5FR= zH_f;yl)VJZn@BxKxN`!|Y*Jhp^|+N|;%E z+P7<8mX=BH@HV_BQ`TGMgD{TOFggTC)E2YJL@u~w)`PYjI+q{n4cKJe=_j#*x=M9K zTIR>KMpC8(N&ME?_$i>5f3_QnL@*Ji;Yh3o`lwt5F;!UWbE#bdrO8EdOXqX@plDNK z1jvA`U8!BuJR2J8>>UPi+gfN2R1WJgAf-JkPM!*%I_md6kxaUIOR?!)(#PwJB~Av1 z$vSr$cOVCf2%Rzq2Ul+@@Zp&9L`;|zh^>r7yW)S^39 zw;`d)JcL>J!;dLG_;-35_sMi_nX9>nXE@9_3a2+%Pl-yVI5~%DbheJ`kFbM@5W2Ze zaLMG0$qpLR+NvBKPaY~&ADQ%KSmSDjj2SlFe!5cC$SSr98!Owp$c|FY&z~nK_JmIb ze}yt{6hvP!%YBW@endSPy;KdrVR0WKkVUa(EdMIvTO_1}Mf}|vq9mixTz|y4)Rl4E zS7sMC;lrdN#g2Va>m)1BkICXmjgtLRlWox;6&Bqf&dsqLCA`LQ`bH;$%Uoh!E}fYg z2+gZ^q2-jouza^rvr<@6gf=5Tjd_3d@hkQ5iT&9OP03H22+UR(Sk7A#r5)Xj0b zLTpo090woB43`;2_v7<)DprvF@rGxb0&6J00+-sAl4#U}M|efDh&r|gpqY3(ka&Ae zSu})?r52eGRJYvJNwoH;rgN#Zz-`hR^>bCzWO)CI+wgynAw_H zZP=iF0Setu`>j1b`U$GC+wr*!E4d$r=Wp{rF2G|UZ&l7;U3aYWOb8f{E6Y$0FA<{Cf8v4xM;|Fdq< z)G?Q9j!4!jVd#s8{AnTqgs}pMFUzh%mPlGT5;dz#{$ato(nUHJ0X3RjmX2CogNjMRAo>MP!4<%9#`gh2}&##`hZ?p>pzSn7meuF`4mOd;|+8S~wvJAm1EENypX{PZrlIl>kUMh^i-TEfj zoloGrGG`oUyGSym?g$SjcK%am&&cWu_8O;0{&p_6qt6tV} zi+McrY$`|G{_K45j8ecX)*BI4cWI}6Ih~kGDerrJav{5xwZ3ajK@1vu3QrPV4@Z2^ zD=iikjfA;RFnj!g^q_4Ol+J?+tAt{D@ls_3uWJ;;Yq``_t;M6z3JsNcYy2h#U3?th z>++ZF79#j+HpQ^w5RLdgmH87x2e0(c6^d7uu;C&~Al5ZjRC6(f-{+cWYC9ExM1@9!YT~h}F6lDLZLg6Yy z7u8vA&}wV7oJb(6>|TlEcGE`w;(@`~9`m5X*+K5COdqg`orNWdJz!zgHh|{>IX2j+ zF@tT+U^2h~!Uu1GZ3Z@=j5IdQdaf`;UjG!gb(If$PW1%0kIxQ5Zt)-&Zw6rj$V=|NPcjeu;e~EINGSzHc&w=8;vW@&`P67Vg3>&3fB_Pw&d5b|Kc1O*3h1m9 zLz-?3Q^|36eq{^WmZ3tx0d3iFTteEMO|Avp2pxYJ_Q%GbKsCkk*UGj`vFcyFs_Z7R zM0(hM4PE_ZDX(MB4evI!3g4v_BYeC&Ayo2fRq(w&56TYLI4!y|#b! zB~&TJl=`$8egGZ^jogmH9=g|L;oBOqs(mX*cgDu2{LOEfTYOQIXnWk^H6<0%TkYL} z2Ed-GYN6O93gp+!197s~y`D?v9&0%!GzG`E%p(#9lF~z&94#zrdi}_2Z)#+2A1(*e zh=sg7p0=+&YNhp6%2n{Rz9AN|R?x<&8e6E876+eP=CmW8_JJfj+Rd}{i%^e!=ne=i zmJ-cFGai=`m@e`7qlU6uP`|P)OJ@*tB^%vm{HVbykxWE$b77JisVaoWx9X6m3NL~7-|Ka$_3SR`trxZcCSac-EEW}OVHrG{`DrQIWN4h1bb{RuE*S@H1 z8Rbgtgxe7u21H|4t zvtp|7%W-wRR=`K2N9c&OeL$zq<#G-k^V>p|CQbQGdKJ@$M-8U>=)4y z+{ujj<{Iiz%-Jn^#ve&cnTxDmWe3XOZsEmZT;w(8gIg7$ar@Sm?dTR~(og;Z0uz+4 z^iz$H{yz+H%*s#Q78u$@D!BKTFyR^aBR@$GMyg{WR`@HDKj3zGcF$LY z!xuyfZqL6Ba$)Yj4IvmSF0`;Z*MqHQlB+qP|KXwbnO8tb&kI zwo^8?xBo+#n4Vp;FdCR!AI1zzZz^E+KAGR=j~LLyS(~t6su|$PZ1&2@O!9u~@yo^H zs-or;O{b)I_Z1IMWSgNIHerii=MGTiNFnG=@US{ZHiAjBA;Ha+>?U~Ju(SPGPlzap zf<`JHVHb#-wmx?KlH749KR7;Le`<{KqM*%o`;rNteQ53e^H=N1yTFI{!LC9%K*mno zhMx{1R^{*ZFyHLCg&!6EJjAVPTpZd!54p250WJ3L$>hDG42gbQ!ga4ga~TeYv^ve* z=H5>}YjK#r#B<*RuUg)rrkgPWWF-5-I-{UZFUe9d!ql4#xoNCPcY%E8vX9;Zsfuwz zMK?28s!^1Ick^{tId*d2_3OdYsRFycWGha0$s8&aw_}SUlPW>JTTA(*yaD@BY2`V! ze+qMDXYIAwgICoSQn_jT%;_;s)$$=#?y`dYK#ECT*n#1}?9s)nzfh5>TIlqPk5WR@ z$_)d0_-0!+idQj0uq#4FX?vS+x)U0Shg?KILqB7e5QR4oWeorDVzVlRG2D(--{fmN z)Mj+b2fe2X!HXt^_VY$VgA^5pgM%O?`F-K@363A|PxFt<5mYPg4)qAt` zzePo6L8-ITF*321(x|rAw){Zo@lR)^-4yIZyV}X5F%Axw~uM zY5r1bxxoy>ea$RI;G)Pb{RjiX3!*d@2H%;)G5>u^@s>n0#8Y)*r zdScP$eU_HcHrMFj%t$DW)(v{L1E&K)`8x`Q+$8f~m2MPhvpI+AnGmwp=MI|C3D1w% zmp99WZFzoZO%FsmglFMDeN1#)KK*{MS4pN%gHkkrUlM6e!xV}lcn29B?f-(#Sr1d3 z3&H~jiP4zWxeW`Wgr4wg1$|5y$<4KJvX6x*0UbsrCP%o%*sd7*u)z1);V1&EjE;Ww z5?@6W_#%yi#M)YwZjx2K)D>M~L83Gms+Oc0W3L*$Bpn`0oP2dXOC(+t^cncP7YyBl z2E~w%5d4Qwbx5zQzeJ1ed5zax=Kwvq(+Hdh$_fjFRN?eGN>INWl|ufAxul(&7EV?) z>ENW41a6r`dL7+kCz`e%KUNYRBTuBn=$3O~-2a>%kOxo2pA|v~NCvRu`OmF?|C+FW zo&TW`P(kM30sg%y>0g3>ob$js^S2hI=Yr20HGYc@fm=78wQW2X{`YG5Z&3gs8|*6l z-?j1QIL}L@zmaCaCA0slVEP>8d4B#kO8U!RD9^L?&jFt25Pky);Qa#lol$r$`aGWa zEo%AdPtoVm#dCz`j^uBI8sg_;@Q-fgbHL|**>Au)l3#$&yt04v(w>9<`(pna5&)

3=T%@22|i;@lK}6aUL_E6BirIS2qCfp