【问题标题】:Regex to validate date in PHP using format as YYYY-MM-DD正则表达式使用 YYYY-MM-DD 格式验证 PHP 中的日期
【发布时间】:2013-11-15 09:47:20
【问题描述】:

我正在尝试制作日期正则表达式验证器。我遇到的问题是我正在使用 "date" 类型的输入字段,这在 Chrome 中就像一个魅力;它在 Chrome 中打开了一个类似日历的功能,但在其余部分它什么也不做,所以我决定手动输入其余部分的日期。

这是我的错误信息(我正在寻找 YYYY-MM-DD 格式):

$date_regex ='#^(19|20)\d\d[\- /.](0[1-9]|1[012])[\- /.](0[1-9]|[12][0-9]|3[01])$#';
$hiredate = $_POST['hiredate'];
if (!preg_match($date_regex, $hiredate)){
    $errors[] = 'Your hire date entry does not match the YYYY-MM-DD required format.';
}

我知道有很多关于这个的例子,但我已经尝试了 20 个,但我无法解决它。也许我错过了什么。

这里是输入字段,如果有点相关:

<input type="date" name="hiredate" />

【问题讨论】:

  • 为什么不按 - 分解并使用 checkdate() 代替?
  • 有标准程序吗?我在另一个帖子中找到了它,但对我不起作用。仅供参考,我想让他们像 YYYY/MM/DD 或 YYYY.MM.DD 或 YYYY-MM-DD 一样插入。为了不过度约束他们。
  • 提供 3 个单独的 &lt;input&gt; 框是否更容易,并带有适当的最大长度和仅数字验证,这些验证在后端连接成正确的格式?如果一个人keypressed 2 位数,您可以在每个输入框中添加侦听器以转到下一个。用户不会对您需要什么格式表示支持,如果这不是他们个人的原生格式,您充其量只会让他们感到沮丧
  • 我实际上是这么想的,但是记住有些月份有 28-29 天,而其他月份有 31 天,这不会让事情变得更复杂吗?我的猜测是正则表达式没问题,因为我在很多帖子中都看到过它。也许我的错误处理都是错误的......但你可能有一点。
  • 我会建立一个逻辑,上面写着If insert fails then slap user in face...我希望一个人知道不要在日期字段中越界,否则你可能不应该雇用他们:)

标签: php regex date preg-match


【解决方案1】:

不要使用正则表达式,使用DateTime::createFromFormat可以获得相同的结果

// specify your date's original format, in this example m/d/Y (e.g. 08/31/2013)
$format = "m/d/Y";
$hireDate = DateTime::createFromFormat($format, $_POST['hiredate']);
if(!$hireDate) {
 // createFromFormat returns false if the format is invalid;
} else {
   //change it to any format you want with format() (e.g. 2013-08-31)
   echo $hireDate->format("Y-m-d");
}

您可以在这里阅读更多内容:

http://php.net/manual/en/datetime.createfromformat.php

但是,这个问题似乎与 PHP 完全无关。

PHP 运行在后端,看来您遇到了前端问题。

我也怀疑问题出在您使用的输入类型上。如果某个浏览器不支持您指定的输入类型,则默认为文本。看这里:

http://jsfiddle.net/FKGCA/

我的浏览器不知道&lt;input type="whatever" /&gt; 是什么,所以它默认输入类型为“文本”。如果我将这 4 个输入包装在 &lt;form action="myForm.php" method="POST"&gt;&lt;/form&gt; 标记中,浏览器会将输入发送到服务器,因为服务器不关心/知道输入是否隐藏、单选按钮、选择、文本或密码。服务器只接收原始数据。

您的问题很可能出在您的 Javascript 上,而不是您的 PHP 上。尝试查看不显示您的小部件的浏览器是否告诉您页面中存在某种错误。

Safari 和 Firefox 有开发/调试工具,对 IE 不太确定。

【讨论】:

  • 这正是我所说的。 “小部件”在 Chrome 中工作,并在其他中转换为文本输入类型。这正是我想要验证的。我有日期格式并将字段分成三个,然后从那里开始。
  • 明白了,在这种情况下,jQuery 就派上用场了。否则,您将需要测试是否支持:diveintohtml5.info/detect.html#input-types,如果不支持。您将不得不使用基于 javascript 的替代方案(如 jQuery)
【解决方案2】:

您的正则表达式不起作用,因为您有未转义 / 分隔符。

YYYY-MM-DD 格式验证日期的正则表达式如下:

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

它将验证年份以1920 开头,月份不大于12 并且不等于0,并且日期不大于31 并且不'不等于0

Example Online

使用您的初始示例,您可以像这样对其进行测试:

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

if (!preg_match($date_regex, $hiredate)) {
    echo '<br>Your hire date entry does not match the YYYY-MM-DD required format.<br>';
} else {
    echo '<br>Your date is set correctly<br>';      
}

Example Online

【讨论】:

  • 是的,这没问题。我使用了很多正则表达式的变体,我一定是把它改得很糟糕。伊利亚·罗斯托夫采夫 (Ilia Rostovtsev) 的眼光不错。
【解决方案3】:

在一行语句中检查并验证YYYY-MM-DD 日期

function isValidDate($date) {
    return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m)
        ? checkdate(intval($m[2]), intval($m[3]), intval($m[1]))
        : false;
}

详见我的回答here

不要盲目使用DateTime::createFromFormat 来验证日期。让我们取一个不存在的日期2018-02-30 看看:

$d = DateTime::createFromFormat("Y-m-d", "2018-02-30");
var_dump((bool) $d); // bool(true)

是的,它返回true,而不是您可能预期的false。更有趣:

$d = DateTime::createFromFormat("Y-m-d", "2018-99-99");
var_dump((bool) $d); // bool(true)

还有true...所以,它只验证位数。再试一次:

$d = DateTime::createFromFormat("Y-m-d", "ABCD-99-99");
var_dump($d); // bool(false)

终于false

从这个sn-p我们可以看出这里发生了什么:

$d = DateTime::createFromFormat("Y-m-d", "2018-02-30");
var_dump($d);

// var_dump OUTPUT
object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2018-03-02 16:41:34.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}

如您所见,当我们传递不存在的2018-02-30 时,DateTime 对象包含2018-03-02。我假设这是因为 2018 年 2 月有 28 天,即最大日期是 2018-02-28,当我们度过这一天 30 时,createFromFormat 只是在 2018-02-01 上增加 30 天,并在没有任何先前日期验证的情况下创建新日期。

【讨论】:

    猜你喜欢
    • 2020-04-09
    • 2012-01-03
    • 2023-04-07
    • 2017-07-10
    • 1970-01-01
    • 2014-03-30
    • 2011-11-02
    • 2013-07-04
    • 2012-03-06
    相关资源
    最近更新 更多