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

时间:2011-01-18 15:04:42

标签: php regex performance date

我正在为codeigniter编写一个输入验证方法来检查日期格式。我实际上只是在测试脚本中执行此操作以使功能得以确定。我有一些有用的东西,但我想看看我是否接近这个最佳(或最差)的方式。

非常具体我看下半场,我评论指出我的意思。

<?

$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 个答案:

答案 0 :(得分:1)

你为什么要这样做? PHP有几种方法可以确定某些东西是否是有效日期,并且这些方法已经完成,稳定且使用起来更快。

<?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 ) ) . "\n";
}

这些日期都已成功解析,每个日期的结果均为2011-01-18。如果我们在谈论格式本身,您可能希望考虑以下内容:

<?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 ) . "\n";
        }
    }
}

我认为这些天PHP的编写日期函数不是必需的,我们有语言中的所有工具吗?这是一些文档:

答案 1 :(得分:1)

为什么不使用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);

然后,只需针对输入运行它:

if (preg_match('/' . $pattern . '/', $date, $match)) {
    $year = $match['year'];
    $month = $match['month'];
    $day = $match['day'];
} else {
    echo "Date not in proper format";
}

但总的来说,根据您的需要,我只使用strtotimedate_parse_from_format ...