如何提前知晓Carbon::parse()支持的有效相对日期格式?
问题解决:Carbon::parse()相对日期字符串解析异常与可靠格式指南
问题核心
在Laravel/Vue项目中使用Carbon::parse()处理用户输入的相对日期字符串时,发现部分格式虽能通过解析但返回错误结果:
- 当前日期为2023-10-26时,
'first day of next month'返回正确的2023-11-01 - 但
'first day of next week'返回错误的2023-09-01,'first day of next year'返回错误的2023-10-01
同时存在两个疑问:
Carbon::hasRelativeKeywords()是否仅识别文档列举的格式?- 哪些相对日期格式能保证解析结果正确?
解析异常原因
Carbon的parse()方法底层依赖PHP原生的strtotime()函数,而'first day of next week'和'first day of next year'并不是strtotime()支持的标准语法。这类非标准格式会被函数误解析,导致结果不符合预期。
'first day of next month'是strtotime()明确支持的格式,因此能得到正确结果。
解决方案
1. 自定义非标准格式的解析逻辑
针对无法被正确解析的格式,手动编写逻辑实现预期效果:
// 处理'first day of next week' $nextWeekFirstDay = Carbon::now()->startOfWeek()->addWeek(); // 处理'first day of next year' $nextYearFirstDay = Carbon::now()->startOfYear()->addYear();
2. 构建输入验证白名单
只允许用户输入经过验证的可靠相对日期格式,避免解析异常:
$validRelativeFormats = [ 'tomorrow', 'yesterday', 'today', 'next sunday', 'last monday', 'this friday', 'next month', 'last year', 'first day of this month', 'last day of previous month', '+3 days', '-2 weeks', '+1 year' ]; // 验证用户输入是否在白名单内 if (!in_array(strtolower($userInput), $validRelativeFormats)) { // 抛出验证错误 }
3. 相对日期的二次校验
结合Carbon::hasRelativeKeywords()判断输入为相对日期后,对解析结果做逻辑校验:
$input = 'first day of next year'; if (Carbon::hasRelativeKeywords($input)) { $date = Carbon::parse($input); // 校验是否为下一年的1月1日 if ($date->year !== Carbon::now()->year + 1 || $date->month !== 1 || $date->day !== 1) { // 解析结果不符合预期,触发错误处理 } }
可靠的相对日期格式清单
以下是Carbon官方文档明确支持且经过验证的相对日期格式:
- 基础时间点:
tomorrow、yesterday、today - 星期相关:
next [weekday](如next sunday)、last [weekday](如last monday)、this [weekday](如this friday) - 月份/年份相关:
next month、last year、first day of this month、last day of previous month、last day of this year - 间隔式:
+[n] days(如+3 days)、-[n] weeks(如-2 weeks)、+[n] year(如+1 year)
关于Carbon::hasRelativeKeywords()的说明
该方法仅检查字符串中是否包含Carbon预定义的相对关键字(如next、last、tomorrow、yesterday等),不验证格式是否能被正确解析。即使返回true,也不代表parse()会得到正确结果,必须结合实际解析后的逻辑校验。
内容的提问来源于stack exchange,提问作者Ronald Baljeu
相关产品推荐
相关产品推荐

