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 { private static final List 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 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 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); } }