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

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the reply. Was 100% spot and very well explained.
For the check to be ready for copy/paste it should have the initial check as well: if (!$dateTime || !empty($errors['warning_count'])) { :)
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).

1 Comment

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.