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