为何PHP中new DateTime('2012')会返回当前日期?
问题描述
我在PHP中遇到了一个奇特的行为,百思不得其解,不确定这是预期特性还是Bug,希望有人能解释其原因。
PHP的DateTime类通常能很好地解析多种格式的日期字符串:
echo (new DateTime('today'))->format('Y-m-d'); // 输出2024-08-15 echo (new DateTime('2012-02-18'))->format('Y-m-d'); // 输出2012-02-18 echo (new DateTime('2012-02'))->format('Y-m-d'); // 输出2012-02-01 echo (new DateTime('5 may'))->format('Y-m-d'); // 输出2024-05-05 echo (new DateTime('6 days ago'))->format('Y-m-d'); // 输出2024-08-09
但当仅传入年份时,却会返回当前日期:
echo (new DateTime('2012'))->format('Y-m-d'); // 输出2024-08-15
起初我以为传入无效日期或格式时会默认返回当前时间,但事实并非如此,以下情况均会抛出错误:
echo (new DateTime('fart'))->format('Y-m-d'); echo (new DateTime('1'))->format('Y-m-d'); echo (new DateTime('last may'))->format('Y-m-d'); echo (new DateTime('2012-02-48'))->format('Y-m-d');
为何传入单独年份会返回当前日期?根据其他情况的表现,我预期要么返回该年份的1月1日,要么抛出错误,但返回当前日期的选择非常奇怪。
(注:我并非寻求获取任意年份1月1日的方法,只是好奇PHP为何有此特殊行为。)
解答
这是PHP DateTime解析器的预期行为,而非Bug,核心逻辑如下:
格式匹配规则:
PHP的DateTime依赖预定义的日期格式规则解析字符串,单独的四位数字(如"2012")不符合任何有效格式——标准年份格式需要搭配月、日(如YYYY-MM-DD)或至少月份(如YYYY-MM),单独的YYYY不属于预定义的部分日期格式。错误判定逻辑:
完全无意义的字符串(如"fart")、明显无效的日期(如"2012-02-48")或无法关联到任何日期组件的数字(如"1")会被判定为不可解析,因此抛出DateTimeException;但四位数字属于"看起来像日期组件但不完整"的输入,解析器不会直接报错。回退机制:
当解析器无法将字符串匹配为有效日期时,会回退到使用当前系统时间,这就是传入单独年份返回当前日期的原因。
补充说明
- 像
"2012-02"这样的YYYY-MM格式属于预定义的部分日期,解析器会自动补全日为01,因此返回2012-02-01。 - 如果需要让单独的年份被解析为该年的1月1日,必须明确指定格式,例如:
echo DateTime::createFromFormat('Y', '2012')->format('Y-m-d'); // 输出2012-01-01
内容的提问来源于stack exchange,提问作者DMJ
相关产品推荐
相关产品推荐

