Java读取XLSX文件时日期字段格式异常、解析报错如何解决?
问题原因
- 直接调用
Cell.toString()获取日期值的逻辑错误:POI的Cell.toString()方法不会读取你在Excel中设置的M/d/yyyy自定义格式,会使用POI内置的默认规则输出日期字符串,因此会得到05/Jan/2021这类带英文月份、不符合预期格式的结果。 - 后续对该不符合规则的字符串做分隔符替换、用
M/d/yyyy模板解析/格式化的操作,自然会抛出格式不匹配的异常。
解决方案
你不需要通过字符串中转处理日期,正确逻辑是直接读取单元格的日期对象,再用目标格式做格式化:
- 判断单元格为数值类型且是日期格式,调用
getDateCellValue()方法直接获取JavaDate对象 - 用你定义的日期格式化模板直接格式化该
Date对象,得到目标格式的字符串
修正后的代码如下:
import org.apache.poi.ss.usermodel.DateUtil; // ...其余引入和原有代码保持一致 XSSFWorkbook wb1 = new XSSFWorkbook(fis1); XSSFSheet sheet1 = wb1.getSheetAt(0); ArrayList<String> arraylist = new ArrayList<>(); for (Row row : sheet1) { Cell cell = row.getCell(4); Cell cell2 = row.getCell(5); CellType type = cell2.getCellType(); // 增加日期格式判断,避免普通数值单元格被误处理 if (type == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell2)) { // 直接读取单元格的日期对象,不需要做字符串转换 Date date = cell2.getDateCellValue(); SimpleDateFormat dateFor = new SimpleDateFormat("M/d/yyyy"); String newdate = dateFor.format(date); arraylist.add(cell + "-" + newdate); } }
优化建议
SimpleDateFormat是线程不安全的类,如果你的代码是多线程环境运行,建议使用Java 8及以上版本提供的DateTimeFormatter替代,示例逻辑如下:
// DateTimeFormatter是线程安全的,可以定义为全局常量复用 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy"); // 格式化逻辑 String newdate = date.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDate() .format(formatter);
内容的提问来源于stack exchange,提问作者NewBond007
相关产品推荐
相关产品推荐

