Excel日期在PHP中显示为数字是因为其内部用序列号存储(如2024-01-01对应45292),PHP读取时未自动转换;PhpSpreadsheet需用excelToDateTimeObject()转换,注意1904日期系统偏移及1900闰年bug。

Excel日期在PHP里为什么变成一串数字?
Excel内部用“序列号”存日期,比如2024-01-01对应45292(从1900-01-01起算)。PHP读取时不会自动转换,直接拿到的就是这个整数——不是时间戳,也不是字符串,所以date()或strtotime()会失效。
用PhpSpreadsheet解析Excel日期的正确姿势
如果你用的是PhpSpreadsheet(官方推荐替代PHPExcel),关键在单元格值的获取方式:
- 别用
$cell->getValue()——它返回原始序列号(如45292)或字符串(取决于Excel格式) - 改用
$cell->getFormattedValue()——它按Excel单元格设置的格式返回字符串(如"2024/1/1"),但依赖Excel本身是否设置了日期格式 - 最稳的方式是:先判断类型,再用
PhpSpreadsheet\Shared\Date::excelToDateTimeObject()转为DateTime对象
$dateValue = $cell->getValue();
if (is_numeric($dateValue) && $dateValue > 1) {
$dateTime = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($dateValue);
echo $dateTime->format('Y-m-d H:i:s');
}手动处理Excel序列号要注意的坑
Excel有1900和1904两种日期系统,而PhpSpreadsheet默认按1900系统计算。如果源文件是Mac旧版Excel生成的(启用1904日期系统),直接套用excelToDateTimeObject()会偏移1462天。
- 检查工作簿是否启用1904系统:
$spreadsheet->getProperties()->getYear1904(),返回true即启用 - 手动校正:若为1904系统,需先给序列号加
1462再转换 - 注意Excel的“伪闰年”bug:它错误地认为1900年2月29日存在,所以
60对应1900-02-29(实际不存在),PhpSpreadsheet已内部处理该异常,无需额外判断
用simplexlsx或xlswriter等轻量库时怎么处理?
这类库不内置日期转换逻辑,只返回原始数值。你得自己实现换算:
立即学习“PHP免费学习笔记(深入)”;
- 通用公式:
$unixTimestamp = ($excelDate - 25569) * 86400(25569是1970-01-01在Excel 1900系统中的序列号) - 但要注意:Excel序列号含小数部分表示时间(如
45292.5是中午),所以必须保留浮点精度 - 转换后用
date('Y-m-d H:i:s', (int)$unixTimestamp)即可,但(int)会截断秒级以下精度,建议用DateTime::setTimestamp()更准
复杂点在于跨平台日期系统、1900闰年兼容、以及毫秒级时间精度丢失——这些细节一旦忽略,生产环境里日期可能批量错一天。



















