dtz30833
dtz30833
2011-01-18 15:04

定义日期格式,正则表达式匹配和检查有效性 - 同行评审

  • date
  • regex
  • php
  • performance
已采纳

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"; 
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dongmiyu8979 dongmiyu8979 10年前

    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...

    点赞 评论 复制链接分享
  • dstbp22002 dstbp22002 10年前

    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:

    点赞 评论 复制链接分享