I'm writing a input validation method for codeigniter to check date format. I'm actually just doing it in a test script to get the functionality nailed down. I've got something that works but I'd just like see if I'm approaching this the best (or worst) way.
Really specifically I'm looking at the second half, I've commented to point out what I mean.
<?
$input = $_POST['input']; //text input of intended format
$date = $_POST['date']; //text input of date in matching format
//examples: y-m-d, Y.M.D, m/D/Y (Case has no affect)
//I'm setting up a regex string based on given format
$pattern = preg_replace('/[yY]/','([0-9]{4})',$input);
$pattern = preg_replace('/[mM]/','([0-9]{1,2})',$pattern);
$pattern = preg_replace('/[dD]/','([0-9]{1,2})',$pattern);
//escaping slashes (if used as date delimiter)
$pattern = str_replace('/','\/',$pattern);
echo "Format : " . $input . "<br />";
echo "Date : " . $date . "<br/>";
echo "============" . "<br />";
echo "<br/>";
//if given date matches given format
if(preg_match('/^'.$pattern.'$/',$date,$matches)) {
echo 'YAY A MATCH! <br/>';
//From here down seems like it could be improved, seems a bit brute force
//All of this below, is trying to get the order of the format so I can feed the proper values
//to the checkdate() function to check date validity.
preg_match('/[yY]/', $input, $match_year,PREG_OFFSET_CAPTURE);
preg_match('/[mM]/', $input, $match_month,PREG_OFFSET_CAPTURE);
preg_match('/[dD]/', $input, $match_day,PREG_OFFSET_CAPTURE);
if ($match_year[0][1] < $match_month[0][1] && $match_year[0][1] < $match_day[0][1]) {
$year = $matches[1];
array_splice($matches,1,1);
}
else if ($match_year[0][1] > $match_month[0][1] && $match_year[0][1] > $match_day[0][1]) {
$year = $matches[3];
array_splice($matches,3,1);
}
else {
$year = $matches[2];
array_splice($matches,2,1);
}
if ($match_month[0][1] < $match_day[0][1]) {
$month = $matches[1];
$day = $matches[2];
}
else {
$month = $matches[2];
$day = $matches[1];
}
echo "<br/>";
echo "<br/>";
echo $month . ' / ' . $day . ' / ' . $year . "<br/>";
if (checkdate($month,$day,$year)) {
echo "This is a valid date.";
}
else {
echo "This is not a valid date";
}
}
else {
echo "Given date does not match given format";
}
Why not just do it all in one regex using named subpatterns?
$search = array(
'/[yY]/',
'/[mM]/',
'/[dD]/',
);
$replace = array(
'(?P<year>[0-9]{4})',
'(?P<month>[0-9]{1,2})',
'(?P<day>[0-9]{1,2})',
);
$pattern = preg_replace($search, $replace, $input);
Then, just run it against the input:
if (preg_match('/' . $pattern . '/', $date, $match)) {
$year = $match['year'];
$month = $match['month'];
$day = $match['day'];
} else {
echo "Date not in proper format";
}
But in general depending on your needs I'd just use strtotime
or date_parse_from_format
...
Why are you doing this? PHP has several ways to determine whether or not something is a valid date, and those are done, stable, and faster to use.
<?php
error_reporting( E_ALL | E_STRICT );
$dates = array(
'18-01-2011 16:22',
'2011-01-18 16:22',
'11-01-18 16:22'
);
foreach( $dates as $date ) {
echo strftime( '%Y-%m-%d', strtotime( $date ) ) . "
";
}
These dates are all successfully parsed, and the result is 2011-01-18 for each of those. If we're talking about the formatting itself, you might wish to consider the following:
<?php
error_reporting( E_ALL | E_STRICT );
$dates = array(
'18-01-2011 16:22',
'2011-01-18 16:22',
'11-01-18 16:22'
);
$formats = array(
'Y-m-d',
'Y-m-d H:i:s',
'd-m-y',
'd/m/Y'
);
foreach( $dates as $date ) {
if( strtotime( $date ) ) { // validate date.
$datetime = new DateTime( $date );
foreach( $formats as $format ) {
echo $datetime->format( $format ) . "
";
}
}
}
I don't think writing a function for dates should be necessary for PHP these days, we have all the tools in the language? Here's some documentation: