
本文讲解如何将 jQuery Datepicker 生成的“07/29/2022 - 07/30/2022”格式日期范围字符串安全拆解、校验并转换为标准日期格式(如 Y-m-d),最终存入 Laravel 数据库的 starts_at 和 ends_at 字段。
本文讲解如何将 jquery datepicker 生成的“07/29/2022 - 07/30/2022”格式日期范围字符串安全拆解、校验并转换为标准日期格式(如 `y-m-d`),最终存入 laravel 数据库的 `starts_at` 和 `ends_at` 字段。
在使用 jQuery Datepicker 的双日期选择(如 daterange 插件)时,前端常将起止日期合并为单个字符串提交,例如 '07/29/2022 - 07/30/2022'。后端需准确分离、解析并标准化这两个日期,否则直接调用 Carbon::createFromFormat() 会因格式不匹配或残留空格/分隔符触发 Trailing data 或 The separation symbol could not be found 等解析错误。
✅ 正确解析步骤
首先,使用 explode() 拆分字符串,并配合 array_map('trim', ...) 清除首尾空格——这是关键一步,因为用户输入或插件渲染可能引入不可见空白:
$rawInput = $request->input('datepicker'); // e.g. "07/29/2022 - 07/30/2022"
$dates = array_map('trim', explode('-', $rawInput));
// 结果:['07/29/2022', '07/30/2022']
接着,分别解析起止日期。注意:Carbon::createFromFormat() 的第一个参数是期望的输入格式(非输出格式),第二个参数是待解析的字符串,返回 Carbon 实例;.format('Y-m-d') 才是转换为数据库兼容的 DATE 格式(推荐使用 Y-m-d 而非 y-m-d,后者为两位年份易引发歧义):
use Carbon\Carbon;
$startsAt = Carbon::createFromFormat('m/d/Y', $dates[0])->format('Y-m-d'); // 2022-07-29
$endsAt = Carbon::createFromFormat('m/d/Y', $dates[1])->format('Y-m-d'); // 2022-07-30
⚠️ 注意:若 $dates[0] 或 $dates[1] 为空、格式错误(如 07-29-2022)、或年份超出范围,createFromFormat() 会抛出异常。务必添加异常捕获或前置验证。
✅ 强烈建议:添加请求验证
在控制器中不应仅依赖前端传入格式,而应通过 Laravel 验证规则确保输入合规。可在 StoreRequest 或控制器中加入正则校验:
$request->validate([
'datepicker' => [
'required',
'string',
'regex:/^\d{1,2}\/\d{1,2}\/\d{4}\s*-\s*\d{1,2}\/\d{1,2}\/\d{4}$/',
],
]);
该正则确保输入严格匹配 m/d/Y - m/d/Y(允许分隔符两侧有空格)。更健壮的做法是结合 after_or_equal:start_date 规则验证结束日期不早于开始日期。
✅ 最终保存示例
$data = [
'starts_at' => $startsAt,
'ends_at' => $endsAt,
// 其他字段...
];
Model::create($data);
若数据库字段类型为 TIMESTAMP 或 DATETIME,且需包含时间,可进一步设置默认时间(如 00:00:00):
$startsAt = Carbon::createFromFormat('m/d/Y', $dates[0])->startOfDay()->toDateTimeString(); // 2022-07-29 00:00:00
? 总结
- ❌ 避免对已解析的 Carbon 实例再次调用 createFromFormat()(如原代码中 Carbon::parse(...) → createFromFormat(...) 是冗余且错误的);
- ✅ 始终先 explode + trim 再解析,消除空格干扰;
- ✅ 使用 Y-m-d(四位年份)而非 y-m-d,避免 2030 年后日期歧义;
- ✅ 在业务逻辑前强制验证输入格式与逻辑合理性,提升系统健壮性。










