02 月(2 月)的日期验证程序检查格式 'Y-m' 失败?

Date validator checking format 'Y-m' failing for month 02 (February)?

根据 PHP 手册中 function reference for checkdate 下的置顶评论,我抓取了日期和时间验证器的代码并修改了它以供我使用,如下所示:

function so_validate_date( $date, $format ) {
    $d = DateTime::createFromFormat( $format, $date );
    return $d && $d->format( $format ) == $date;
}

这个逻辑对我来说很有意义,但它有问题,因为当月份是 02(二月)时,它无法验证格式 Y-m 的日期。

例如

function test_validate_date( $date = '2011-02', $format = 'Y-m' ) {
    $d = DateTime::createFromFormat( $format, $date );
    echo $d->format( $format ); // outputs 2011-03, NOT 2011-02!
}

test_validate_date() 的输出,我预计是 2011-02,令人惊讶的是,2011-03。我不知道为什么。

我在这里错过了什么?感谢任何修复逻辑的帮助(或我在这里出错的任何地方)。

您的问题是,当您使用 DateTime::createFromFormat 并且未指定日期的一部分时,PHP 会替换该字段的当前值:

If format does not contain the character ! then portions of the generated time which are not specified in format will be set to the current system time.

所以,鉴于今天是 12 月 30 日(可能是你所在的第 29 日),你正在尝试创建日期 2011-02-30,PHP 可以方便地转换为 2011-03-02,然后以 Y-m 格式输出为 2011-03

要解决此问题,请在格式字符串的开头指定 !,以便

portions of the generated time not provided in format, as well as values to the left-hand side of the !, will be set to corresponding values from the Unix epoch (1970-01-01 00:00:00 UTC).

function so_validate_date( $date, $format ) {
    $d = DateTime::createFromFormat( "!$format", $date );
    return $d && $d->format( $format ) == $date;
}

echo so_validate_date('2011-02', 'Y-m') ? 'true' : 'false';

输出:

true

Demo on 3v4l.org