Ali
Ali

Reputation: 267077

How to validate a MYSQL Date in PHP?

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

Answers (6)

raveren
raveren

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:

  • treats dates like 20111-03-21 as invalid - unlike checkdate()
  • no possible PHP warnings (if any one parameter is provided, naturally) - unlike most explode() solutions
  • takes leap years into account unlike regex-only solutions
  • fully compatible with the mysql DATE 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

sebilasse
sebilasse

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

Shir Gans
Shir Gans

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

gpojd
gpojd

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

Paulo
Paulo

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

thomasrutter
thomasrutter

Reputation: 117343

If they are 3 separate drop-downs, you will need to validate them as three separate values.

Ie,

  • Validate that the year column is numeric and between whatever years are valid in your app
  • Validate that the month column is numeric
  • Validate that the day column is numeric
  • Validate that they are all valid values using checkdate()

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

Related Questions