Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP DateTime accepting invalid date

Tags:

date

php

datetime

I'm having trouble using the PHP DateTime class, and more specifically the DateTime::createFromFormat().

I get a date from a string, then try to instanciate a DateTime object, using DateTime::createFromFormat(). But, when I give this function a date that cannot exist, it is still working, returning me a valid DateTime object, with a valid date, which isn't the date I gave it.

Code example :

$badDate = '2010-13-03';
$date = DateTime::createFromFormat('Y-m-d', $badDate);

var_dump($date);

/*
object(DateTime)#284 (3) {
["date"]=>
string(19) "2011-01-03 10:01:20"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
*/

Any ideas? I really need a way to check date validity.

Thank you.

Edit:

I just found why, see my answer.

like image 728
Clement Herreman Avatar asked Apr 04 '11 08:04

Clement Herreman


2 Answers

DateTime::createFromFormat doesn't throw exception/return false when the given date is impossible. It try to guess the expected date.

If you give it '2010-01-32' (as in Januar, 32th), it will return a DateTime object containing Februar, 1st (Januar 31th + 1 day). Must be logical... in some weird twisted way.

To check the validity, you must check the DateTime::getLastErrors() which contains warning, like for my case :

array(4) {
  ["warning_count"]=>
  int(1)
  ["warnings"]=>
  array(1) {
    [10]=>
    string(27) "The parsed date was invalid"
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
}

This behavior seems to come from the UNIX timestamp which PHP calculate, based on the year, month and date you give it (even if the date is invalid).

like image 161
Clement Herreman Avatar answered Nov 04 '22 05:11

Clement Herreman


You have to make use of DateTime::getLastErrors() which will contain the error The parsed date was invalid.

$badDate = '2010-13-03';
$date = DateTime::createFromFormat('Y-m-d', $badDate);
if( DateTime::getLastErrors()['warning_count'] > 0 ){
 //not a correct date
}else{
 //correct date
 print $date->format('Y-m-d');
}
like image 14
krookedking Avatar answered Nov 04 '22 03:11

krookedking