Laravel中Maatwebsite Excel导入日期变为1970-01-01问题求助
问题:Laravel导入Excel日期全部变为1970-01-01
在Laravel项目中使用Maatwebsite Excel实现Excel数据导入功能,数据已成功写入数据库,但Excel中原本的01/01/2022和31/12/2022日期,导入后全部变成了01/01/1970。
相关代码
AlokasicutiImport类
<?php namespace App\Imports; use Carbon\Carbon; use App\Models\Alokasicuti; use Illuminate\Support\Facades\Log; use Maatwebsite\Excel\Concerns\ToModel; class AlokasicutiImport implements ToModel { public function startRow(): int { return 2; } /** * @param array $row * * @return \Illuminate\Database\Eloquent\Model|null */ public function model(array $row) { if(isset($row[0]) && isset($row[2])) { if(!Alokasicuti::where('id_karyawan',$row[0])->where('id_jeniscuti',$row[2])->exists()) { $data = [ 'id_karyawan' => $row[0] ?? null, 'id_settingalokasi'=> $row[1] ?? null, 'id_jeniscuti' => $row[2] ?? null, 'durasi' => $row[3] ?? null, 'mode_alokasi' => $row[4] ?? null, 'tgl_masuk' => Carbon::parse($row[5])->format("Y-m-d") ?? null, 'tgl_sekarang' => Carbon::parse($row[6])->format("Y-m-d") ?? null, 'aktif_dari' => Carbon::parse($row[7])->format("Y-m-d") ?? null, 'sampai' => Carbon::parse($row[8])->format("Y-m-d") ?? null, ]; Alokasicuti::create($data); }else{ Log::info('id pegawai dan tanggal absensi sudah ada'); } } else{ Log::info('Row 1 kosong'); } } }
导入控制器方法
public function importexcel(Request $request) { Excel::import(new AlokasicutiImport, request()->file('file')); return redirect()->back(); }
问题原因
- 日期格式解析不匹配:
Carbon::parse()默认优先识别MM/DD/YYYY格式,而你的Excel日期是DD/MM/YYYY(日/月/年),导致解析错误。例如31/12/2022中31作为月份不存在,解析失败后返回Unix时间戳0对应的日期1970-01-01。 - 空值处理逻辑错误:代码中
Carbon::parse($row[7])->format("Y-m-d") ?? null的写法无效,因为即使解析失败,Carbon::parse()也会返回一个Carbon实例(对应1970-01-01),不会触发?? null。 - Excel日期存储形式问题:如果Excel中的日期是以数值形式存储(Excel内部将日期转为从1900-01-01开始的天数),直接用Carbon解析数值会导致完全错误的结果。
解决方案
方案1:指定日期格式解析
针对DD/MM/YYYY格式,使用Carbon::createFromFormat()明确指定解析规则,同时先判断单元格是否为空:
$data = [ // ... 其他字段 'tgl_masuk' => !empty($row[5]) ? Carbon::createFromFormat('d/m/Y', $row[5])->format('Y-m-d') : null, 'tgl_sekarang' => !empty($row[6]) ? Carbon::createFromFormat('d/m/Y', $row[6])->format('Y-m-d') : null, 'aktif_dari' => !empty($row[7]) ? Carbon::createFromFormat('d/m/Y', $row[7])->format('Y-m-d') : null, 'sampai' => !empty($row[8]) ? Carbon::createFromFormat('d/m/Y', $row[8])->format('Y-m-d') : null, ];
方案2:处理Excel数值型日期
如果Excel中的日期是数值格式,使用PhpSpreadsheet内置的转换方法:
use PhpOffice\PhpSpreadsheet\Shared\Date; // ... $data = [ // ... 其他字段 'aktif_dari' => !empty($row[7]) ? Date::excelToDateTimeObject($row[7])->format('Y-m-d') : null, 'sampai' => !empty($row[8]) ? Date::excelToDateTimeObject($row[8])->format('Y-m-d') : null, ];
方案3:兼容多种日期格式
如果不确定Excel日期格式,可以先尝试解析,失败时再用指定格式:
function parseExcelDate($date) { if(empty($date)) return null; try { $carbonDate = Carbon::parse($date); if($carbonDate->year < 2000) { // 解析结果异常,尝试用DD/MM/YYYY $carbonDate = Carbon::createFromFormat('d/m/Y', $date); } return $carbonDate->format('Y-m-d'); } catch (\Exception $e) { return null; } } // 在$data中使用: 'aktif_dari' => parseExcelDate($row[7]), 'sampai' => parseExcelDate($row[8]),
内容的提问来源于stack exchange,提问作者akhiratunnisa
相关产品推荐
相关产品推荐

