9

Hi I seem to be having trouble getting the datetime method to work as expected? I may be doing something wrong?

// 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

Robbo_UK
  • 11,351
  • 25
  • 81
  • 117

3 Answers3

53

The thing about DateTime::createFromFormat is that there are two kinds of unexpected input it recognizes: the kind that generates errors, and the kind that generates warnings.

Input such as '56/56/fail' produces an error, so false is returned and everything is good. However, '56/56/2012' gives not an error but a warning, and is actually parsed as the 56th day of the 56th month of 2012. Since 2012 does not have 56 months, PHP internally changes this to 2016 + 8 months = Aug 2016. And since that month does not have 56 days, we have another compensation to Sep 2016 + (56 - 31) days = 25 Sep 2016. So while unexpected, this is in fact correct.

If you want to disallow this automatic adjustment, you have to wrap the DateTime factory method and use DateTime::getLastErrors as reference:

$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";
}

See it in action.

Jon
  • 428,835
  • 81
  • 738
  • 806
2

PHP is a strange beast (to say the least). 56/56/2012 results in all additional months and days to be added to the date until it becomes correct (god only knows the logic behind this).

Petr Abdulin
  • 33,883
  • 9
  • 62
  • 96
  • 3
    I suspect the logic is that it lets the programmer do some lazy date calcs. If you want to add 90 days or 18 months to something, you can just jam the numbers in there without doing the calcs, wrapping the months/years yourself, etc, and PHP will sort it out for you and return what you want. – Peter Barton Jan 14 '15 at 12:08
0

Actually this is correct: For example if you create a date with 2012/04/31 (invalid date) PHP returns 2012/05/01 (first day of may)!

This is done behind the scenes

ab_dev86
  • 1,952
  • 16
  • 21