Reputation: 267077
Users would select their date from 3 dropdowns (day, month, year). I will combine them on server-side to make a string like '2008-12-30'. How can I then validate to make sure this date was in the right format/numeric only, etc?
Upvotes: 10
Views: 15063
Reputation: 18541
I personally found this to be the correct and elegant way to determine if the date is both according to format and valid:
20111-03-21
as invalid - unlike checkdate()
explode()
solutionsDATE
format (10.03.21 is the same as 2010-03-21)Here's the method you can use:
function isValidMysqlDate( string $date ): bool
{
return preg_match( '#^(?P<year>\d{2}|\d{4})([- /.])(?P<month>\d{1,2})\2(?P<day>\d{1,2})$#', $date, $matches )
&& checkdate($matches['month'],$matches['day'], $matches['year']);
}
Upvotes: 22
Reputation: 4618
I am using this function:
<?php
function validateMysqlDate( $date ){
if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $date, $matches)) {
if (checkdate($matches[2], $matches[3], $matches[1])) {
return true;
}
}
return false;
}
// check it:
$a = validateMysqlDate('2012-12-09 09:04:00');
$b = validateMysqlDate('20122-12-09 09:04:00');
$c = validateMysqlDate('2012-12_09 09:04:00');
$d = validateMysqlDate('');
var_dump( $a );
var_dump( $b );
var_dump( $c );
var_dump( $d );
?>
$a is true, the others are false - and that is correct
The function from Raveren (above) will not cover valid dates with timestamps !!! $a returns false there! And btw: checkdate() would return true for $b although it is not a valid mysql datetime
Upvotes: 6
Reputation: 2027
Just had the same issue. I wrote a short function that checks if the format is correct, and also if the date is real:
function valid_mysql_date($str){
$date_parts = explode('-',$str);
if (count($date_parts) != 3) return false;
if ((strlen($date_parts[0]) != 4) || (!is_numeric($date_parts[0]))) return false;
if ((strlen($date_parts[1]) != 2) || (!is_numeric($date_parts[1]))) return false;
if ((strlen($date_parts[2]) != 2) || (!is_numeric($date_parts[2]))) return false;
if (!checkdate( $date_parts[1], $date_parts[2] , $date_parts[0] )) return false;
return true;
}
hope it helps.
Upvotes: 1
Reputation: 23065
You can check that the date is valid using checkdate. If you want to make sure that the values are numeric and the correct length, you could do something as simple as an is_int ctype_digit and a strlen combination before you build the date.
// untested
if( !ctype_digit)( $month ) || strlen( $month ) != 2 ) {
// handle error
}
// repeat for $day and $year
if ( checkdate( $month, $day, $year ) {
// do your work
}
Upvotes: 2
Reputation: 4333
If you have three dropdowns then the values coming from the dropdowns should always be numbers since you control the values associated with the month (shown below). This would then lead to the conclusion that the combined result is valid.
<option value="01">January</option>
If you provide provide assistance entries in the drop downs such as "Select a Month" then you can make that value 0 and ensure that the values coming from each drop box is greater than zero.
There is the possibility that someone will alter the HTML form to provide other values. If this is a concern then you can use the PHP function ctype_digit() to check that each value provided is actually a numerical digit.
If your concern is that the date is actually valid the use the checkdate() function.
Upvotes: -1
Reputation: 117343
If they are 3 separate drop-downs, you will need to validate them as three separate values.
Ie,
Or, you could just cast them all to integer, combine them together into a date, and see if the resulting date is valid. Ie,
$time = mktime(0, 0, 0, (int)$_POST['month'], (int)$_POST['day'], (int)$_POST['year']);
// in this example, valid values are between jan 1 2000 (server time) and now
// modify as required
if ($time < mktime(0, 0, 0, 1, 1, 2000) || $time > time())
return 'Invalid!';
$mysqltime = date('Y-m-d', $time);
// now insert $mysqltime into database
The downside to this method is that it'll only work with dates within the Unix timestamp range ie 1970 to 2038 or so.
Upvotes: 5