Niloct
Niloct

Reputation: 10015

date_create_from_format accepts invalid dates as an input

PHP date_create_from_format function is accepting non-existent, though format-valid dates.

I would like this function to behave like the date command:

niloct@HP-Mini:~$ date --date="29/02/2011" +%s
date: invalid date `29/02/2011'

though this is what happens in php:

$tmp = date_create_from_format('d/m/Y H:i:s',"29/02/2011 00:00:00", timezone_open('America/Sao_Paulo'));
var_dump($tmp);
/*
output: object(DateTime)#28 (3) { ["date"]=> string(19) "2011-03-01 00:00:00" ["timezone_type"]=> int(3) ["timezone"]=> string(17) "America/Sao_Paulo" }
*/

Can this automatic conversion be avoided and the function return -1 in this case ?

niloct@HP-Mini:~$ php -v
PHP 5.3.3-1ubuntu9.3 with Suhosin-Patch (cli) (built: Jan 12 2011 16:08:14) 

Thank you.

Upvotes: 3

Views: 1774

Answers (3)

user2102442
user2102442

Reputation: 1

This will work:

 $format = 'd/m/Y H:i';
   $date = DateTime::createFromFormat($format, Input::get('start_date'));

  return $date->format('Y/m/d H:i'); 

Upvotes: -1

Niloct
Niloct

Reputation: 10015

I found that calling date_get_last_errors after date_create_from_format already gives you all kind of validations on the parsed string, in the arrays warnings and errors, and counters warning_count and error_count.

So just checking the counters for zero warnings and errors is enough.

Revised code with some tests:

<?
$appTZ = 'America/Sao_Paulo';

function datetimeCreateErrorsWarnings() {
    $obj = date_get_last_errors();  
    return ($obj['error_count'] > 0) || ($obj['warning_count'] > 0);
}

function datetimeToUnixTS($data) {
    global $appTZ;

    $fmt = "d/m/Y H:i:s";

    $dtobj = date_create_from_format($fmt, $data . " 00:00:00", timezone_open($appTZ)); 

    if ($dtobj) {
        if (!datetimeCreateErrorsWarnings()) {
            return date_timestamp_get($dtobj);
        }
    }

    //Second try, $data is auto-suficient
    $dtobj = date_create_from_format($fmt, $data, timezone_open($appTZ));

    if ($dtobj) {
        if (!datetimeCreateErrorsWarnings()) {
            return date_timestamp_get($dtobj);
        }
    }

    return -1;
}

$test = array(
    'asdfasdf',
    '',
    "28/02/2011",
    "29/02/2011",
    "28/02/2011 00:00:90"
);

for ($i=0; $i<count($test); $i++) {
    $tmp = datetimeToUnixTS($test[$i]);
    var_dump($tmp);
    echo "<p>";
}
?>

The above script calculates the unix timestamp of the datetime created.

Upvotes: 0

Jon
Jon

Reputation: 437544

You can use a combination of date_parse_from_format and checkdate to see if it's a valid calendar date.

Example:

$date = date_parse_from_format('d/m/Y H:i:s',"29/02/2011 00:00:00");

if (checkdate($date['month'], $date['day'], $date['year'])) {
    echo "Valid date";
}
else {
    echo "Invalid date";
}

Upvotes: 5

Related Questions