如何使用PHP的modify()方法仅设置DateTime的年份?
关于PHP DateTime::modify()仅修改年份的问题
根据PHP官方文档,理论上可以使用modify()方法仅修改DateTime的年份部分,但这仅对世纪部分为60-99的年份生效:
(new DateTime)->modify('1960')->format('c'); // '1960-01-25T19:09:44+00:00'
若年份的世纪部分为00-59(含),则会被解析为时间:
(new DateTime)->modify('1959')->format('c'); // '2024-01-25T19:59:00+00:00'
这情有可原,解析器无法区分用户输入的是日期还是时间。
如何强制解析器将输入识别为年份?根据复合格式的文档,字面量T应能区分输入的日期和时间部分,但测试后发现无效:
(new DateTime)->modify('1959T')->format('c'); // '2024-01-25T19:59:00+00:00'
仅指定T而无后缀并无效果。
尝试添加时间后缀的写法也不符合预期:
(new DateTime)->modify('1959T0000')->format('c'); // '0000-01-25T19:59:00+00:00'
原本以为设置年份时时间会自动设为午夜,但实际情况是:年份被设为0000,1959仍被当作时间。基于此,反转写法却能得到预期结果:
// 注意这里的空格可以和`T`互换 (new DateTime)->modify('0000 1959')->format('c'); // '1959-01-25T00:00:00+00:00'
这种写法确实有效(但会附带修改时间的副作用),但我们无法确定它理应生效(或未来仍能生效)——所有已文档化的有效复合格式中,时间从未出现在日期之前,为何反向指定反而可行?
尝试在日期后强制指定00:00作为时间会导致解析失败,因为解析器认为重复指定了时间:
(new DateTime)->modify('1959T00:00')->format('c'); (new DateTime)->modify('1959T00:00:00')->format('c'); // DateTime::modify(): Failed to parse time string (1959T00:00:00) at position 4 (T): Double time specification
我了解已有关于仅设置年份的类似问题,但本文仅询问:是否存在仅使用modify()方法设置年份的正确写法?现有解决方案需重新显式设置月日,不够优雅且不应有此必要。
尽管'0000 1959'似乎是有效的年份设置方式,但存在两个可优化的点:
- 该写法未被文档化,若有官方认可的实现方式则更佳
- 当前写法会附带修改时间的副作用,若有仅修改年份的替代方案则更佳
此外,若有熟悉PHP内部实现的人士能解释为何'0000 1959'/'0000T1959'会按此方式解析(即时间在前、日期在后),这会十分有趣——这种行为自首次实现以来从未改变。
内容的提问来源于stack exchange,提问作者Quolonel Questions
相关产品推荐
相关产品推荐

