tags:

views:

342

answers:

6

I found the regular expression for MM/DD/YYYY at http://www.regular-expressions.info/regexbuddy/datemmddyyyy.html but I don't think I am using it correctly.

Here's my code:

$date_regex = '(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d';

$test_date = '03/22/2010';
if(preg_match($date_regex, $test_date)) {
  echo 'this date is formatted correctly';  
} else {
  echo 'this date is not formatted correctly';  
}

When I run this, it still echoes 'this date is not formatted correctly', when it should be saying the opposite. How do I set this regular expression up in php?

+5  A: 

Its probably better to use strtotime() which will convert nearly any human-readable date format to a unix timestamp. - http://php.net/manual/en/function.strtotime.php

DCD
+1 Agreed. Although, strtotime is probably slower.
Jud Stephenson
How will strtotime help me see if the user entered the string in the MM/DD/YYYY format? Can you give me an example? I am thoroughly confused.
zeckdude
strtotime can read the date in any format and you can verify to see if its returned value is valid.
Jud Stephenson
A: 

Your regex needs delimiters:

/(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/

Coronatus
It also needs the backslashes escaped -- the ones on the `\d`s. EDIT: And the escapes on the character classes need double escapes.
Billy ONeal
It also doesn't capture the year correctly, it'll only capture the 19 or 20... not 2010.
fiXedd
@Billy: the backslashes don't need to be escaped if the enclosing string literal uses single-quotes, e.g. `'/(19|20)\d\d/'`. In fact, PHP is pretty forgiving about that even in double-quoted strings, but it's usually best to use single-quotes anyway.
Alan Moore
+4  A: 

you can use the checkdate() function as well. No need regex.

$str="03/22/2010";
list($mth,$day,$yr)=explode("/",$str);
var_dump(checkdate($mth,$day,$yr));
ghostdog74
+1 for a simple, non-regex based solution. However, the example may need a little work. I believe it'd match the string `"03/22/2010/2011"` or `"03/22/2010///"`
Frank Farmer
@Frank Farmer: explode("/",$str, 3); maybe? That will limit explode to 3 elements, meaning 03/22/2010/2011 will come out as { 03 , 22 , 2010/2011 }, where the year part is now obviously invalid.
Duroth
+3  A: 

You need correct delimiters around the pattern.

$date_regex = '~(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d~';
toscho
+2  A: 

The problem is one of delimeters and escaped characters (as others have mentioned). This will work:

$date_regex = '/(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/';

$test_date = '03/22/2010';
if(preg_match($date_regex, $test_date)) {
  echo 'this date is formatted correctly';
} else {
  echo 'this date is not formatted correctly';
}

Note that I added a forward-slash to the beginning and ending of the expression and escapped (with a back-slash) the forward-slashes in the pattern.

To take it one step further, this pattern won't properly extract the year... just the century. You'd need to change it to /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]((?:19|20)\d\d)/ and (as Jan pointed out below) if you want to make sure the whole string matches (instead of some subset) you'll want to go with something more like /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]((?:19|20)\d\d)$/.


As others have mentioned, strtotime() might be a better option if you're just trying to get the date out. It can parse almost any commonly used format and it will give you a unix timestamp. You can use it like this:

$test_date = '03/22/2010';

// get the unix timestamp for the date
$timestamp = strtorime($test_date);

// now you can get the date fields back out with one of the normal date/time functions. example:
$date_array = getdate($timestamp);
echo 'the month is: ' . $date_array['month'];    
fiXedd
The "year" group doesn't work right after your change. You need to isolate the alternation in its own group, preferably non-capturing: `((?:19|20)\d\d)`.
Alan Moore
No, that's what you get for not testing it on dates in the years 1900 to 1999. You also didn't test it on `1212/12/201010`.
Jan Goyvaerts
+1  A: 

To use this regex to validate dates in PHP code, you need to correctly format it as a string with additional regex delimiters as the PHP preg functions require. You also need to add anchors to force the regex to match the entire string (or else fail to match):

$date_regex = '%\A(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d\z%'; 

$test_date = '03/22/2010'; 
if(preg_match($date_regex, $test_date)) { 
  echo 'this date is formatted correctly';   
} else { 
  echo 'this date is not formatted correctly';   
} 

Of course, a library call would be better in this situation. The regex allows invalid dates such as February 31st.

The regex can be useful if you want to scan a string for dates. In that case you don't need the anchors. You may still need an extra check to exclude invalid dates. That depends on whether your input is know to contain only valid dates or not.

Jan Goyvaerts