|
package com.ruoyi.common.easyExcel;
|
|
import cn.hutool.core.util.StrUtil;
|
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 com.ruoyi.common.exception.GlobalException;
|
import org.apache.poi.ss.usermodel.DateUtil;
|
import org.springframework.format.annotation.DateTimeFormat;
|
|
import java.math.BigDecimal;
|
import java.text.ParseException;
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
import java.util.Locale;
|
import java.util.Objects;
|
import java.util.TimeZone;
|
import java.util.List;
|
import java.util.Arrays;
|
|
public class DateConverter implements Converter<Date> {
|
private static final List<String> DEFAULT_DATE_FORMATS = Arrays.asList(
|
"yyyy/M/d","dd-M-yyyy", "M/d/yyyy", "yyyy-MM-dd","yyyy-MM",
|
"yyyy.MM.dd","yyyy.MM","yyyy","yyyy年MM月dd日","yyyy年MM月","yyyy年"
|
);
|
|
@Override
|
public Class<Date> supportJavaTypeKey() {
|
return Date.class;
|
}
|
|
@Override
|
public CellDataTypeEnum supportExcelTypeKey() {
|
return CellDataTypeEnum.STRING;
|
}
|
|
/**
|
* 这里读的时候会调用
|
*
|
* @param cellData excel数据 (NotNull)
|
* @param contentProperty excel属性 (Nullable)
|
* @param globalConfiguration 全局配置 (NotNull)
|
* @return 读取到内存中的数据
|
*/
|
@Override
|
public Date convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
|
try {
|
String stringValue = "";
|
// 1. Excel 单元格是数字类型(如 40969),代表日期
|
if (cellData.getType() == CellDataTypeEnum.NUMBER) {
|
//这里有可能是 2025年,是数字类型,也可能是2025.08也是数字,有可能是2025/08/01(这种excel读取是数字类型)
|
//2000以后都是5位数
|
if(cellData.getNumberValue().toString().contains(".")
|
|| cellData.getNumberValue().compareTo(new BigDecimal("2050")) <= 0){
|
stringValue = cellData.getNumberValue().toString();
|
}else {
|
double numericDate = cellData.getNumberValue().doubleValue();
|
Date date = DateUtil.getJavaDate(numericDate, false); // HSSF 日期基准是 1900-01-01
|
// System.out.println(cn.hutool.core.date.DateUtil.format(date, "yyyy-MM-dd"));
|
return date;
|
}
|
}else {
|
stringValue = cellData.getStringValue();
|
}
|
try {
|
Date parsedDate = parseDate(stringValue);
|
if (parsedDate != null) {
|
// System.out.println(cn.hutool.core.date.DateUtil.format(parsedDate, "yyyy-MM-dd"));
|
return parsedDate;
|
} else {
|
throw new ParseException("日期格式不匹配", 0);
|
}
|
} catch (Exception e) {
|
throw new ParseException("日期格式不匹配", 0);
|
}
|
} catch (Exception e) {
|
throw new GlobalException("日期格式错误,请保证时间格式为:yyyy/m/d, yyyy-MM-dd, dd-M-yyyy, M/d/yyyy");
|
}
|
}
|
|
private Date parseDate(String dateStr) throws ParseException {
|
for (String defaultFormat : DEFAULT_DATE_FORMATS) {
|
SimpleDateFormat sdf = new SimpleDateFormat(defaultFormat, Locale.getDefault());
|
sdf.setTimeZone(TimeZone.getDefault());
|
try {
|
return sdf.parse(dateStr);
|
} catch (ParseException e) {
|
// 继续尝试下一个格式
|
}
|
}
|
return null;
|
}
|
|
public boolean isValidDate(Date date) {
|
if (date == null) {
|
return false;
|
}
|
|
// 定义日期格式
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
|
sdf.setLenient(false); // 关闭宽松模式,严格校验日期
|
|
// 将 Date 转换成字符串,再转换回 Date,确保格式正确
|
String dateStr = sdf.format(date);
|
return cn.hutool.core.date.DateUtil.parse(dateStr) == null ? false:true;
|
}
|
|
/**
|
* 写的时候会调用
|
*
|
* @param value java value (NotNull)
|
* @param contentProperty excel属性 (Nullable)
|
* @param globalConfiguration 全局配置 (NotNull)
|
* @return 写出到excel文件的数据
|
*/
|
@Override
|
public WriteCellData<Date> convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
|
DateTimeFormat annotation = contentProperty.getField().getAnnotation(DateTimeFormat.class);
|
String format = Objects.nonNull(annotation) ? annotation.pattern() : "yyyy-MM-dd";
|
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
|
sdf.setTimeZone(TimeZone.getDefault());
|
String result = sdf.format(value);
|
return new WriteCellData<>(result);
|
}
|
}
|