3
function validateDate( $date )
{ 
    echo $date;
    //2012-08-24 20:30:00
    if(preg_match('/^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([1-2]{1})([0-9]{1}):([0-5]{1})([0-9]{1}):([0-5]{1})([0-9]{1})$/', $date) >= 1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

This always returns false. I used an only tool to build the regular expression and it was working fine there. Trouble started when I added the "/" to the regex. Somehow PHP seems to require these but I dont know why and I dont know why it breaks my regex.

It should return TRUE for sth. like "2012-08-24 20:30:00" and FALSE for "asdf2012-08-24 20:30:00asdf" or anything thats not acording to my regex

As some users pointed out my function returns true for the sample date "2012-08-24 20:30:00". However it does that only if i manually set $date='2012-08-24 20:30:00'. If i call the function elsewhere in my code with the exact same string it returns false. Does anyone know why?

Braiam
  • 1
  • 11
  • 47
  • 78
marius2k12
  • 1,041
  • 1
  • 18
  • 32
  • 3
    That is NOT how you validate a date. It'll allow `9999-99-99`. While allowing up to year 9999 is good foresight, I don't think ninetyninghtuary is a real month. – Marc B Sep 07 '12 at 17:35
  • 2
    Consider using strtotime() or the DateTime class instead of that – Bgi Sep 07 '12 at 17:35
  • Btw, the `/` is not required--only some matched expression delimiter. You could use `|`, `~`, or even an alphanumeric character if you like, as long as you match it at the end (and escape instances of that same character used in the expression body). – Brian Warshaw Sep 07 '12 at 17:39
  • That function works for the example dates you provided. – Explosion Pills Sep 07 '12 at 17:42
  • Marc B - maybe i want these dates to be validated Brian - could you elaborate on how i have to change my code so that its works? – marius2k12 Sep 07 '12 at 17:43
  • @ExplosionPills You are right, when i set $date='2012-08-24 20:30:00' in my function it works, if i use the param $date that gets passed by me calling the function elsewhere in my code with the exact same string it doesnt. Any ideas? :( – marius2k12 Sep 07 '12 at 17:45
  • @MarcB Programmers from the early days of a computing didn't believe 2000 was a valid year either. Maybe the OP's right by allowing *yet to discover* months. – Tchoupi Sep 07 '12 at 17:49
  • Or maybe i wanted to get my function working in generall before fine tuning it? ;) – marius2k12 Sep 07 '12 at 17:51
  • @user1259801 - are you sure that it's the exact same string? There's no extraneous spaces that have snuck on the end or anything? – andrewsi Sep 07 '12 at 18:02
  • like @andrewsi said, var_dump($date); at the begining of function. when you fix that problem, you will have another one. your function doesnt validate if date is corrent, it will return true for 2000-43-43 11:11:11 .... look at my simple answer below... – Glavić Sep 07 '12 at 18:04
  • why do you use () in regex? no need for that if you are only validation, and not fetching data from string... another thing is hour part, you wrote ([1-2]{1})([0-9]{1}), this means that hour cannot be bellow 10, soo time 05:20:30 won't be validated. it should be [0-2]{1}[0-9]{1} – Glavić Sep 07 '12 at 18:28
  • @user1259801: do a `var_dump()` on that 'bad' date, and see if the reported string length is what you expect. if there's ANY hidden characters in there, it will be different and probably cause the regex to fail. Remember that browsers will silently hide/ignore spaces, line breaks, tabs, etc... – Marc B Sep 07 '12 at 19:48
  • couple more dupes predating this one: https://stackoverflow.com/search?q=validate+date+php – Gordon Mar 15 '14 at 12:32

3 Answers3

26

Why use regex? Use DateTime class.

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

You can use this function for all kind of date/time validations. Examples:

var_dump(validateDate('2012-02-28 12:12:12')); # true
var_dump(validateDate('2012-02-30 12:12:12')); # false
var_dump(validateDate('2012-02-28', 'Y-m-d')); # true
var_dump(validateDate('28/02/2012', 'd/m/Y')); # true
var_dump(validateDate('30/02/2012', 'd/m/Y')); # false
var_dump(validateDate('14:50', 'H:i')); # true
var_dump(validateDate('14:77', 'H:i')); # false
var_dump(validateDate(14, 'H')); # true
var_dump(validateDate('14', 'H')); # true

var_dump(validateDate('2012-02-28T12:12:12+02:00', 'Y-m-d\TH:i:sP')); # true
# or
var_dump(validateDate('2012-02-28T12:12:12+02:00', DateTime::ATOM)); # true

var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', 'D, d M Y H:i:s O')); # true
# or
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
# ...
Glavić
  • 42,781
  • 13
  • 77
  • 107
3

Returns true for me. Try this regex instead:

function validateDate($date) {
  echo $date;
  if( !preg_match("/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/",$date,$m)) return false;
  if( !checkdate($m[1],$m[2],$m[0])) return false;
  if( $m[3] > 23) return false;
  if( $m[4] > 59) return false;
  if( $m[5] > 59) return false;
  return true;
}

It is easier to validate format in RegEx, followed by validating content with targeted functions, than to try and do everything in RegEx.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • Thanks for your answer. Its true that my function returns true when i manually set $date='2012-08-24 20:30:00' but it does return FALSE when i call the function elsewhere in my code with this exact string, any ideas why? – marius2k12 Sep 07 '12 at 17:50
  • Are you sure the string doesn't have spaces before or after? Or even non-printable characters? Where is the string coming from? – Niet the Dark Absol Sep 07 '12 at 20:25
2

What you are asking about are the delimiters. Read this article in PHP.net's manual: RegExp - Delimiters

When using the PCRE functions, it is required that the pattern is enclosed by delimiters. A delimiter can be any non-alphanumeric, non-backslash, non-whitespace character.

And:

Often used delimiters are forward slashes (/), hash signs (#) and tildes (~). The following are all examples of valid delimited patterns.

Community
  • 1
  • 1
Mike Mackintosh
  • 13,917
  • 6
  • 60
  • 87