我的模式无法匹配ISO风格的日期,为什么?

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;
    }
}

这总是返回false。我使用了一个工具来构建正则表达式,在那里它运行良好。当我向正则表达式添加“/”时,问题开始了。不知何故,PHP似乎需要这些,但我不知道为什么,也不知道为什么它会破坏我的正则表达式。
对于类似“2012-08-24 20:30:00”的内容,它应该返回TRUE,而对于“asdf2012-08-24 20:30:00asdf”或任何不符合我的正则表达式的内容都应该返回FALSE。
正如一些用户指出的那样,我的函数对于样本日期“2012-08-24 20:30:00”返回true。然而,只有当我手动设置$date='2012-08-24 20:30:00'时,它才会这样做。如果我在我的代码的其他地方调用具有完全相同字符串的函数,则会返回false。有人知道原因吗?

3
这不是正确的日期验证方式,它允许9999-99-99这种错误的日期格式。虽然允许使用到9999年是很好的长远考虑,但我想"ninetyninghtuary"并不是一个真实存在的月份。 - Marc B
2
请考虑使用strtotime()或DateTime类来代替那个。 - Bgi
顺便说一下,/并非必需--只需要一些匹配表达式分隔符即可。您可以使用|~或甚至是字母数字字符,只要您在末尾匹配即可(并转义表达式主体中使用的相同字符实例)。 - Brian Warshaw
就像 @andrewsi 所说的,在函数开头使用 var_dump($date);。当你解决了那个问题,你会遇到另一个问题。你的函数没有验证日期是否正确,它会将 2000-43-43 11:11:11 返回为 true....看看我下面的简单答案... - Glavić
还有几个在这之前的重复问题:https://stackoverflow.com/search?q=validate+date+php - Gordon
显示剩余8条评论
3个回答

26

为什么要使用正则表达式?可以使用DateTime类。

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

您可以使用此函数进行各种日期/时间验证。例如:

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

3
对于我来说返回true。请尝试使用以下正则表达式代替:
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;
}

在正则表达式中,先通过验证格式,然后使用针对性的函数验证内容,比尝试在正则表达式中完成所有操作更容易。

谢谢你的回答。我的函数确实在手动设置$date='2012-08-24 20:30:00'时返回true,但是当我在代码的其他地方使用这个完全相同的字符串调用该函数时,它会返回FALSE。你有什么想法吗? - marius2k12
你确定字符串前后没有空格吗?或者甚至有不可打印的字符?这个字符串是从哪里来的? - Niet the Dark Absol

2
你所询问的是分隔符。请阅读PHP.net手册中的这篇文章:RegExp - Delimiters

使用PCRE函数时,需要将模式括在分隔符中。分隔符可以是任何非字母数字、非反斜杠、非空格字符。

并且:

常用的分隔符有正斜杠(/)、井号(#)和波浪线(~)。以下都是有效的带分隔符的模式示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接