使用DateTime :: createFromFormat验证Year

I have this block of code for validating a correctly formatted date prior to submission to a DB insert using DateTime::createFromFormat(). I'm expecting the date format to convert 'DD/MM/YYYY' to 'YYYY-MM-DD' or else raise an error.

$dateofbirth = trim($_POST['dateofbirth']);
$date = DateTime::createFromFormat('d/m/Y', $dateofbirth);

$date_errors = DateTime::getLastErrors();
    var_dump($date_errors);
if ($date_errors['warning_count'] + $date_errors['error_count'] > 0) {
    $dobError = 'Date '.$dateofbirth.' is not a valid DD/MM/YYYY format.';
    $hasError = true;
} else {
    $mysql_dob = $date->format('Y-m-d');
}
error_log($dateofbirth.' -> '.$mysql_dob);

This date works

 $dateofbirth = '30/11/1980'; => 1980-11-30

but this one fail silently

 $dateofbirth = '30/11/80'; => 0080-11-30

since i'm expecting to be notified of the missing century digits. I've read the formatting rules and am using the upper case 'Y' which should ensure a 4 digit year. Any idea's where i'm going wrong?

EDIT

1 - Correct the test date as per OneTrickPony's comment

2 - I added a var_dump of the $date_errors variable. Since the format is 'd/m/Y' and the input is '30/11/80' i am expecting an error or warning but i don't get one.

array(4) {
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
}
30/11/80 -> 0080-11-30

From the documentation for DateTime::createFromFormat

http://www.php.net/manual/en/datetime.createfromformat.php

Returns a new DateTime instance or FALSE on failure.

So rather than checking getLastErrors you should check if $date === false

Change your error check to:

if ($date === false) {
    $dobError = 'Date '.$dateofbirth.' is not a valid DD/MM/YYYY format.';
    $hasError = true;
} else {
    $mysql_dob = $date->format('Y-m-d');
}
$date = DateTime::createFromFormat('d/m/Y', $dateofbirth);

[...]

This date works

$dateofbirth = '30/11/1980'; => 1980-11-30

but this one fail silently

$dateofbirth = '30/11/80'; => 0080-11-30

According to the DateTime::createFromFormat() manual page, the format you provided very expressly looks for a four digit year. It's parsing "80" as the year 80 AD instead of 1980.

To accept a two digit year, you would need to use a lowercase y instead of an uppercase Y. However, this would also then not accept a four digit year.

Your options are:

  1. Validate that the user entered the correct string length before encountering date validation code.
  2. Use string length to determine the format used
  3. Use a regex to check the length of the year and change the format accordingly
  4. If you're breaking out regexes, you'd may as well just use checkdate()
  5. Stop accepting dates in the very weird, nonstandard DD/MM/YYYY format. Where slashes are commonly used, the expected format is actually MM/DD/YYYY instead, which may create significant user confusion.