You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PhpSpreadsheet导入XLSX日期转Carbon格式问题求助

解决PhpSpreadsheet导入Excel日期序列号转Carbon格式的问题

我之前也踩过这个坑!你拿到的25861或者43195.4092014都是Excel日期序列号,和Unix时间戳完全不是一回事:

  • Unix时间戳是从1970年1月1日00:00:00开始的秒数
  • Excel日期序列号是从1900年1月0日(Excel的历史bug,把1900年当成了闰年)开始的天数(带小数的话是一天内的时分秒占比)

直接把这个浮点数当Unix时间戳转肯定会出错,下面给你两种靠谱的解决方法:

方法一:遍历单元格时直接转成Carbon对象(推荐)

放弃用rangeToArray批量获取,改成逐个处理单元格,借助PhpSpreadsheet自带的日期工具类判断并转换:

use PhpOffice\PhpSpreadsheet\Shared\Date;
use Carbon\Carbon;

$sheet = $spreadsheet->getActiveSheet();
$dataArray = [];

// 遍历你需要的行(A2到AO3)
for ($row = 2; $row <= 3; $row++) {
    $rowData = [];
    // 遍历A到AO列的单元格
    $cellIterator = $sheet->getRowIterator($row)->getCellIterator('A', 'AO');
    $cellIterator->setIterateOnlyExistingCells(false); // 包含空单元格

    foreach ($cellIterator as $cell) {
        $column = $cell->getColumn();
        $cellValue = $cell->getValue();

        // 判断当前单元格是否是Excel日期格式
        if (Date::isDateTime($cell)) {
            // 转成PHP DateTime对象,再包装成Carbon
            $dateTime = Date::excelToDateTimeObject($cellValue);
            $rowData[$column] = Carbon::instance($dateTime);
        } else {
            // 非日期单元格按格式化后的值获取
            $rowData[$column] = $cell->getFormattedValue();
        }
    }
    $dataArray[] = $rowData;
}

这个方法的好处是能自动识别所有日期格式的单元格,不管列在哪里,而且PhpSpreadsheet会自动处理Excel的1900/1904日期系统差异,不用额外操心。

方法二:对已获取的序列号进行转换

如果你已经用rangeToArray拿到了数据,也可以单独处理日期列的浮点数:

use PhpOffice\PhpSpreadsheet\Shared\Date;
use Carbon\Carbon;

// 假设$dataArray是你已经获取到的数组
foreach ($dataArray as &$row) {
    // 处理I列的日期
    if (isset($row['I']) && is_float($row['I'])) {
        $dateTime = Date::excelToDateTimeObject($row['I']);
        $row['I'] = Carbon::instance($dateTime);
    }
    // 如果J列也是日期,同理处理
    if (isset($row['J']) && is_float($row['J'])) {
        $dateTime = Date::excelToDateTimeObject($row['J']);
        $row['J'] = Carbon::instance($dateTime);
    }
}
unset($row); // 解除引用

转换后你就可以用Carbon的所有方法了,比如转成特定格式:

echo $row['I']->format('Y-m-d H:i:s'); // 输出1970-10-20 00:00:00

为什么之前的方法不对?

你之前把浮点数当Unix时间戳转,本质是混淆了两种完全不同的时间计量方式:

  • 25861天 = 25861 × 86400 = 2,234,390,400秒,但这个秒数对应的是从1900年开始的时间,不是1970年,所以转出来的日期完全不对。
  • 必须用PhpSpreadsheet的excelToDateTimeObject来处理,它会自动处理起始日期的差异,甚至带小数的时分秒也能准确转换。

内容的提问来源于stack exchange,提问作者user9660776

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:57:53