Excel日期显示为“2026-07-07”但读取为45865,因PhpSpreadsheet默认返回原始序列号;需先判断单元格为数值型且格式代码匹配日期格式,再用Date::excelToDateTimeObject或($excelDate-25569)*86400转换为标准日期。

ThinkPHP导入Excel时,单元格里显示“2026-07-07”,实际读出来却是45865这样的数字,直接入库会导致日期错乱或报错。这是因为Excel内部用序列号存储日期,而PhpSpreadsheet默认返回原始值,不自动转换。
判断单元格是否为日期类型
先获取单元格对象,再检查其数据类型和数字格式代码:
使用$cell->getDataType() === \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC确认是数值型;
再调用$cell->getStyle()->getNumberFormat()->getFormatCode()获取格式字符串,若匹配'yyyy-mm-dd'、'm/d/yyyy'或'[$-F800]dddd, mmmm dd, yyyy'等常见日期格式,则视为日期字段。
立即学习“PHP免费学习笔记(深入)”;
【必须同时满足数值类型+日期格式代码才可执行转换】
转换Excel序列号为标准日期
Excel日期序列号起始点是1900年1月1日(注意:Excel 1900日期系统存在闰年bug,但25569这个基准值已兼容该bug)。
方法一:用PhpSpreadsheet内置函数(推荐)
直接调用\PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($excelDate),返回DateTime对象,再用format('Y-m-d')输出;
方法二:手动计算Unix时间戳
对纯数字日期值,执行$unixTs = ($excelDate - 25569) * 86400,再用date('Y-m-d', $unixTs)格式化;
注意:若$excelDate含小数部分(如45865.5表示当天中午),需保留小数参与计算,否则会丢失时间信息。
处理Delphi时间戳
某些Excel由Delphi生成,其时间戳起点为1899-12-30,数值比Excel序列号大2天。
第一步:识别是否为Delphi时间戳——当数值大于40000且不含“-”时,大概率是;
第二步:减去25569得到天数差,再乘86400转为秒数;
第三步:用date('Y-m-d', $timestamp)输出标准日期;
若原始值是字符串“45865”,需先floatval()转为数值,否则计算结果为0。



















