PHP Regex to check date is in YYYY-MM-DD format

前端 未结 23 1558
终归单人心
终归单人心 2020-11-27 10:05

I\'m trying to check that dates entered by end users are in the YYYY-MM-DD. Regex has never been my strong point, I keep getting a false return value for the preg_match() I

23条回答
  •  清歌不尽
    2020-11-27 10:46

    It's probably better to use another mechanism for this.

    The modern solution, with DateTime:

    $dt = DateTime::createFromFormat("Y-m-d", $date);
    return $dt !== false && !array_sum($dt::getLastErrors());
    

    This validates the input too: $dt !== false ensures that the date can be parsed with the specified format and the array_sum trick is a terse way of ensuring that PHP did not do "month shifting" (e.g. consider that January 32 is February 1). See DateTime::getLastErrors() for more information.

    Old-school solution with explode and checkdate:

    list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0);
    return ctype_digit("$y$m$d") && checkdate($m, $d, $y);
    

    This validates that the input is a valid date as well. You can do that with a regex of course, but it's going to be more fuss -- and February 29 cannot be validated with a regex at all.

    The drawback of this approach is that you have to be very careful to reject all possible "bad" inputs while not emitting a notice under any circumstances. Here's how:

    • explode is limited to return 3 tokens (so that if the input is "1-2-3-4", $d will become "3-4")
    • ctype_digit is used to make sure that the input does not contain any non-numeric characters (apart from the dashes)
    • array_pad is used (with a default value that will cause checkdate to fail) to make sure that enough elements are returned so that if the input is "1-2" list() will not emit a notice

提交回复
热议问题