开发者

PHP DateTime accepting invalid date

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::cr开发者_如何学CeateFromFormat(). 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.


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');
}


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


I found example where validation based on DateTime::getLastErrors() will fail, so better solution would be to compare inputed date with generated date.

Code:

function validateDate($date, $format = 'Y-m-d')
{
    $dt = DateTime::createFromFormat($format, $date);
    return $dt && $dt->format($format) == $date;
}

Use example:

var_dump(validateDate('2012-02-28')); # true
var_dump(validateDate('2012-02-30')); # false

# you can validate and date/time format
var_dump(validateDate('14:50', 'H:i')); # true
var_dump(validateDate('14:99', 'H:i')); # false

# this is the example where validation with `DateTime::getLastErrors()` will fail
var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', DateTime::RSS)); # true
var_dump(validateDate('Tue, 27 Feb 2012 12:12:12 +0200', DateTime::RSS)); # false


Look for checkdate() function at php documentation. It will help you :)


You can do that :

DateTime::getLastErrors()


change

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

into

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

Your given format is wrong, you properly mixed up days and months...

To understand what is behind the magical calculation of dates read this very very good article by Derick Rethans and all comments ;)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜