杰瑞科技汇

Java Excel导入日期如何正确处理?

Java Excel 导入日期处理指南

在Java中处理Excel导入日期数据时,需要注意Excel日期的特殊存储方式,以下是完整的解决方案:

Java Excel导入日期如何正确处理?-图1
(图片来源网络,侵删)

使用Apache POI处理Excel日期

Apache POI是处理Excel文件最常用的Java库。

基本步骤

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExcelDateImporter {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.xlsx");
             Workbook workbook = new XSSFWorkbook(fis)) {
            Sheet sheet = workbook.getSheetAt(0);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            for (Row row : sheet) {
                // 假设日期在第一列
                Cell cell = row.getCell(0);
                if (cell != null) {
                    switch (cell.getCellType()) {
                        case NUMERIC:
                            // 处理日期类型的数字
                            if (DateUtil.isCellDateFormatted(cell)) {
                                Date date = cell.getDateCellValue();
                                System.out.println("日期: " + dateFormat.format(date));
                            } else {
                                // 处理普通数字
                                System.out.println("数字: " + cell.getNumericCellValue());
                            }
                            break;
                        case STRING:
                            // 处理字符串格式的日期
                            String dateStr = cell.getStringCellValue();
                            System.out.println("字符串日期: " + dateStr);
                            break;
                        // 其他类型处理...
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

处理不同日期格式

Excel中的日期可能有多种格式,需要统一处理:

private static Date parseExcelDate(Cell cell) {
    if (cell == null) return null;
    try {
        switch (cell.getCellType()) {
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue();
                } else {
                    // 处理Excel日期序列号
                    double numericValue = cell.getNumericCellValue();
                    return DateUtil.getJavaDate(numericValue);
                }
            case STRING:
                String dateStr = cell.getStringCellValue().trim();
                if (dateStr.isEmpty()) return null;
                // 尝试多种日期格式
                String[] patterns = {
                    "yyyy-MM-dd", "MM/dd/yyyy", "dd-MM-yyyy", 
                    "yyyy年MM月dd日", "yyyyMMdd"
                };
                for (String pattern : patterns) {
                    try {
                        return new SimpleDateFormat(pattern).parse(dateStr);
                    } catch (Exception e) {
                        // 继续尝试下一种格式
                    }
                }
                throw new IllegalArgumentException("无法解析的日期格式: " + dateStr);
            default:
                return null;
        }
    } catch (Exception e) {
        throw new RuntimeException("日期解析失败: " + e.getMessage(), e);
    }
}

使用EasyExcel处理日期

阿里巴巴的EasyExcel库提供了更简单的API:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class EasyExcelDateReader {
    public static void main(String[] args) {
        String fileName = "example.xlsx";
        EasyExcel.read(fileName, DateData.class, new AnalysisEventListener<DateData>() {
            private List<DateData> dataList = new ArrayList<>();
            @Override
            public void invoke(DateData data, AnalysisContext context) {
                dataList.add(data);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                System.out.println("读取完成,共" + dataList.size() + "条数据");
            }
        }).sheet().doRead();
    }
}
// 定义数据模型
class DateData {
    @ExcelProperty(value = "日期", converter = CustomDateConverter.class)
    private Date date;
    // getters and setters
}

自定义日期转换器

如果需要自定义日期格式处理:

Java Excel导入日期如何正确处理?-图2
(图片来源网络,侵删)
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.property.ExcelContentProperty;
public class CustomDateConverter implements Converter<Date> {
    private static final String[] DATE_FORMATS = {
        "yyyy-MM-dd", "yyyy/MM/dd", "yyyy年MM月dd日", 
        "yyyyMMdd", "MM/dd/yyyy", "dd-MM-yyyy"
    };
    @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 Exception {
        String dateStr = cellData.getStringValue();
        for (String pattern : DATE_FORMATS) {
            try {
                return new SimpleDateFormat(pattern).parse(dateStr);
            } catch (Exception e) {
                // 继续尝试下一种格式
            }
        }
        throw new IllegalArgumentException("无法解析的日期格式: " + dateStr);
    }
}

注意事项

  1. Excel日期存储:Excel将日期存储为序列号(1900年1月1日为1)
  2. 时区问题:处理日期时注意时区转换
  3. 1900年bug:Excel认为1900年是闰年,实际不是,需要特殊处理
  4. 空值处理:检查单元格是否为空
  5. 格式验证:验证日期字符串是否符合预期格式

完整示例

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class CompleteExcelDateImporter {
    private static final Map<String, String> DATE_FORMAT_MAP = new HashMap<>();
    static {
        DATE_FORMAT_MAP.put("yyyy-MM-dd", "日期格式: 年-月-日");
        DATE_FORMAT_MAP.put("MM/dd/yyyy", "日期格式: 月/日/年");
        DATE_FORMAT_MAP.put("dd-MM-yyyy", "日期格式: 日-月-年");
        DATE_FORMAT_MAP.put("yyyy年MM月dd日", "中文日期格式");
        DATE_FORMAT_MAP.put("yyyyMMdd", "紧凑日期格式");
    }
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("dates.xlsx");
             Workbook workbook = new XSSFWorkbook(fis)) {
            Sheet sheet = workbook.getSheetAt(0);
            int rowNum = 0;
            for (Row row : sheet) {
                rowNum++;
                System.out.println("\n处理第 " + rowNum + " 行:");
                for (Cell cell : row) {
                    processCell(cell);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void processCell(Cell cell) {
        if (cell == null) {
            System.out.println("单元格为空");
            return;
        }
        switch (cell.getCellType()) {
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    System.out.println("Excel日期格式: " + date);
                } else {
                    double numericValue = cell.getNumericCellValue();
                    System.out.println("数字值: " + numericValue);
                    // 尝试将数字转换为日期
                    try {
                        Date date = DateUtil.getJavaDate(numericValue);
                        System.out.println("转换后的日期: " + date);
                    } catch (Exception e) {
                        System.out.println("无法转换为日期");
                    }
                }
                break;
            case STRING:
                String strValue = cell.getStringCellValue().trim();
                if (strValue.isEmpty()) {
                    System.out.println("空字符串");
                    return;
                }
                // 尝试解析为日期
                for (Map.Entry<String, String> entry : DATE_FORMAT_MAP.entrySet()) {
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat(entry.getKey());
                        Date date = sdf.parse(strValue);
                        System.out.println(entry.getValue() + ": " + date);
                        return;
                    } catch (ParseException e) {
                        // 继续尝试下一种格式
                    }
                }
                System.out.println("无法识别的字符串: " + strValue);
                break;
            case FORMULA:
                System.out.println("公式单元格: " + cell.getCellFormula());
                break;
            default:
                System.out.println("不支持的单元格类型: " + cell.getCellType());
        }
    }
}

代码提供了从Excel导入日期数据的完整解决方案,包括处理不同日期格式、Excel序列号日期和字符串日期等情况,根据实际需求选择适合的方法即可。

分享:
扫描分享到社交APP
上一篇
下一篇