PHP DateTime createFromFormat 功能性

9

你好,我似乎遇到了datetime方法无法按预期工作的问题?我可能做错了什么?

// Passes OK 
$dateTime = DateTime::createFromFormat('d/m/Y', '12/12/2012' );
var_dump($dateTime);

// should fail but returns  - 2016-09-25 
$dateTime = DateTime::createFromFormat('d/m/Y', '56/56/2012' );
var_dump($dateTime);

// correctly returns False 
$dateTime = DateTime::createFromFormat('d/m/Y', '56/56/fail' );
var_dump($dateTime);

// should fail but returns 2019-08-29 09:58:10
$dateTime = DateTime::createFromFormat('m/d/Y', '90/90/2012' );
var_dump($dateTime);

enter image description here

3个回答

53

DateTime::createFromFormat 有个特点,就是会识别出两种类型的意外输入:一种会产生错误,另一种会产生警告。

例如 '56/56/fail' 这样的输入会产生一个错误,因此返回 false ,一切正常。然而,'56/56/2012' 并不会产生错误,只会产生警告,并实际解析为2012年第56个月的第56天。由于2012年不可能有56个月份,PHP内部会将其更改为2016年加上8个月 = 2016年8月。由于这个月没有56天,所以还需要进一步调整至2016年9月25日,因此尽管出乎意料,但实际上是正确的。

如果您想禁止这种自动调整,您需要包装 DateTime 工厂方法,并使用 DateTime::getLastErrors 作为参考:

$dateTime = DateTime::createFromFormat('d/m/Y', '56/56/2012');
$errors = DateTime::getLastErrors();
if (!empty($errors['warning_count'])) {
    echo "Strictly speaking, that date was invalid!\n";
}

点击此处查看实例.


感谢您的回复。非常准确并且解释得非常清楚。 - Robbo_UK
2
为了使检查结果能够进行复制/粘贴,请确保初始的检查也包含在内:if (!$dateTime || !empty($errors['warning_count'])) {:) - Adrian C.

2

PHP是一种奇怪的东西(至少可以这么说)。56/56/2012会导致所有额外的月份和天数被加到日期上,直到它变得正确(只有神知道背后的逻辑)。


3
我猜测这个逻辑是让程序员能够进行一些懒惰的日期计算。如果你想要给某个日期加上90天或18个月,你只需将数字放进去,而不用自己进行计算、包装月份/年份等操作,PHP会为你解决这些问题,并返回你所需的结果。 - Peter Barton

0

实际上这是正确的: 例如,如果您创建了一个日期为2012/04/31(无效日期),PHP将返回2012/05/01(五月份的第一天)!

这是在幕后完成的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接