Excel导入日期变数字,数据库入库异常的排查与修复过程
📌【Bug记录】Excel导入日期变数字,数据库入库异常的排查与修复过程
📖 一、背景
最近在做一个功能:将 Excel 中的用户信息批量导入数据库,其中包含用户的出生日期字段,最初数据库表的 birth_date
字段类型是 varchar
,打算直接把 1995/07/07
这种格式存进去。
开发环境:
- 数据库:MySQL 8.x
- Java 后端:Spring Boot + MyBatis-Plus
- Excel导入库:Apache POI
📖 二、问题描述
在导入过程中,发现原本 Excel 中 1995/07/07
的日期,导入数据库之后变成了 277336 这样的数字。起初以为是导入逻辑出了问题,排查发现其实是 Excel 内部存储日期的机制导致的序列值问题。
📖 三、原因分析
Excel 中的日期本质上是从 1900/01/01 起算的天数序列值,比如:
1900/01/01
→1
1995/07/07
→277336
当我们使用 Apache POI 读取 Excel 时:
- 如果单元格是日期格式,POI 读取到的类型是
NUMERIC
,且是序列值 - 如果不做日期判断和转换,直接当字符串或数字写入数据库,就会把这个序列值存进去
⚠️ 原先数据库字段是 varchar
类型,导致这类数据没做类型约束,直接把数字存进去了。
📖 四、解决方案
📝 方法一:调整数据库字段类型(我最终采用的方法)
将 birth_date
字段的类型由 varchar
改为 date
类型:
ALTER TABLE user_info
MODIFY COLUMN birth_date DATE COMMENT '出生日期';
这样,后续导入时,Apache POI 读取到日期格式,可以直接转成 java.util.Date
,然后插入数据库 date
类型字段,不再出现序列值异常。
📝 方法二:代码层判断日期类型,转成字符串再入库
如果仍想保留 varchar
类型,也可以在导入代码中判断单元格类型:
if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) {Date date = cell.getDateCellValue();SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");String dateStr = sdf.format(date);// 入库 dateStr
}
📝 方法三:导入前调整 Excel 格式
让 Excel 中的日期列先转成文本格式:
- 选中列
- 右键 → 设置单元格格式 → 选择“文本”
- 确认保存
这样导入时,读取到的就是字符串了。
📖 五、总结
📌 这次问题让我彻底搞清楚了 Excel 日期存储的底层原理,也顺便优化了数据库设计。
✅ 建议:
- 日期类型字段,数据库中统一用
date
或datetime
类型,避免后期字符串难以统一格式或做日期运算 - 导入 Excel 时,一定要判断单元格类型,尤其是
CellType.NUMERIC
且DateUtil.isCellDateFormatted
的情况
问题记录就是成长!
👊 希望这篇 bug 修复记录能帮到有同样困扰的朋友们。