views:

345

answers:

5

I'm trying to validate date using PHP.

I'd like following formats to be valid:

d/m/yy
d/m/yyyy
dd/m/yy
dd/m/yyyy
d/mm/yy
d/mm/yyyy
dd/mm/yy
dd/mm/yyyy

I've tried many regular expressions and different variations of checkdate() function. Currently I have something like this:

function _date_is_valid($str)
{
     if(strlen($str) == 0)
         return TRUE;
     if(substr_count($str,'/') == 2)
     {
         if (preg_match("/^((((31\/(0?[13578]|1[02]))|((29|30)\/(0?[1,3-9]|1[0-2])))\/(1[6-9]|[2-9]\d)?\d{2})|(29\/0?2\/(((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))|(0?[1-9]|1\d|2[0-8])\/((0?[1-9])|(1[0-2]))\/((1[6-9]|[2-9]\d)?\d{2}))/", $str))
         {
             $datearray = explode('/',$str);
             if($datearray[2] > 2030)
                 return FALSE;
             return checkdate($datearray[1], $datearray[0], $datearray[2]);
         } 
         else 
         {
             return FALSE;
         }
     }
     return FALSE;
}

This however, validates dates like 11/11/200 and 11/11/200#

How can I validate date to match required format?

Edit: I could check datearray[2] to be between 10 and 30 and 2010 and 2030. But is there a way to check it using regex?

Edit1: return TRUE on strlen($str) == 0 is because I want users to be able to add events without knowing when will the event occur so someone else can qualify the schedule and assign event to certain date later


Just for the record. I ended up doing:

function _date_is_valid($str)
{
    if(strlen($str) == 0) //To accept entries without a date
        return TRUE;
    if(substr_count($str,'/') == 2)
    {
        list($d,$m,$y) = explode('/',$str);
        if(($y >= 10 && $y <= 30) || ($y >= 2010 && $y <= 2030))
        {
            return checkdate($m,$d,$y);
        }
    }
    return FALSE;
}

Thanks for all your answers

+1  A: 

Try this:

function _date_is_valid($str) {
    if (strlen($str) == 0) {
        return TRUE;
    }
    return preg_match('/^(\d{1,2})\/(\d{1,2})\/((?:\d{2}){1,2})$/', $str, $match) && checkdate($match[2], $match[1], $match[3]) && $match[2] <= 2030;
}
Gumbo
why return TRUE?
erenon
I want to allow date to be left empty or in valid format. It's sort of event calendar where you can book an event for a certain date or book an event and someone else will allocate the date to it later
LukeP
Doesn't check the day or month are valid.
Douglas Leeder
@Douglas Leeder: `checkdate` checks for valid dates.
Gumbo
Sorry - didn't notice the horizontal scroll. And the preg_match fit on the displayed width.
Douglas Leeder
+4  A: 

If it will always will be date / month / year you can use checkdate:

function _date_is_valid($str)
{
    $array = explode('/', $str);

    $day = $array[0];
    $month = $array[1];
    $year = $array[2];

    $isDateValid = checkdate($month, $day, $year);
    return $isDateValid;
}
marvin
Should be checkdate(), not check_date(). And you might want do a isset() for the $array indices. Other than that, looks good to me. +1
fireeyedboy
oh yes, you are right, it is checkdate(), copied from the question without checking it. Thanks
marvin
What if there are no two separating `/`?
Gumbo
A: 

You can user PEAR's validation class for validation for the date.

Please chek below.

PEAR VALIDATE

Its just a coding without bug..

Avinash
A: 

how about if(strtotime($str) !== FALSE) $valid = TRUE;

antpaw
-1: OP was very specific about what formats to accept. Your solution allows for many more formats.
fireeyedboy
and also there's an issue between dd/mm/yyyy and mm/dd/yyyy
LukeP
+5  A: 
function _date_is_valid($str)
{
    list($d, $m, $y) = explode('/', $str);

    return checkdate($m, $d, $y);
}
Alix Axel
Should be checkdate(), not check_date(). Other than that, looks good to me. +1
fireeyedboy
if you don't check the count of '/' it will throw a php notice or warning on invalid strings
antpaw
I modified this a bit to not validate dates after certain year as php checkdate() validates years like 20111 which in this case is not what I want
LukeP
What if there are no two separating `/`?
Gumbo