【问题标题】:Using filter_var() to verify date?使用 filter_var() 来验证日期?
【发布时间】:2012-11-24 15:25:01
【问题描述】:

我显然没有正确使用filter_var()。我需要检查用户输入的日期是否有效,格式为“dd/mm/yyyy”。

这只是返回我作为日期传递的任何内容,而我希望它返回日期或 0/null/FALSE,以防输入字符串看起来不像日期:

$myregex = "/\d{2}\/\d{2}\/\d{4}/";
print filter_var("bad 01/02/2012 bad",FILTER_VALIDATE_REGEXP,array("options"=>array("regexp"=> $myregex)));

如果其他人使用此功能检查日期,我做错了什么?我应该使用其他函数来验证表单字段吗?

谢谢。

【问题讨论】:

标签: php filtering


【解决方案1】:

使用正则表达式来验证日期是个坏主意。想象一下99/99/9999 很容易被视为有效日期。你应该checkdate

bool checkdate ( int $month , int $day , int $year )

简单用法

$date = "01/02/0000";
$date = date_parse($date); // or date_parse_from_format("d/m/Y", $date);
if (checkdate($date['month'], $date['day'], $date['year'])) {
    // Valid Date
}

【讨论】:

  • 注意,如果您执行date_parse( '2019-02-313' );,则结果将31 作为日值。也许在这种情况下,您需要检查字段 $date['error_count'] 的值
【解决方案2】:
$myregex = '~^\d{2}/\d{2}/\d{4}$~';

正则表达式匹配,因为您只需要字符串中的模式 anywhere。你想要的是only那个模式,没有别的。所以添加^$

请注意,这并不意味着该值是有效日期99/99/9999 将通过该测试。我会使用:

if (!DateTime::createFromFormat('d/m/Y', $string))

【讨论】:

  • 根据我的测试,您的createFromFormat() 条件不会捕获像99/99/9999 这样的字符串。不过它会捕获baddate
  • createFromFormat() 认为日期有效2019-02-31
  • @Zauker sigh PHP…
【解决方案3】:

在 PHP 中验证日期的一种简单方便的方法是 strtotime 函数。 您可以只用一行来验证日期:

strtotime("bad 01/02/2012 bad"); //false
strtotime("01/02/2012"); //1325455200 unix timestamp

【讨论】:

  • 非常适合短期修复。但要小心 MM/DD/YYYY 被向后读取到 DD/MM/YYYY 或其他类型的陷阱。
  • 您是否也尝试使用此值 '2019-02-31' ? :) strtotime 回复一个 Unix 时间戳,但也许你必须考虑这个日期无效。
【解决方案4】:

为什么要使用繁重的正则表达式,而有一个原生的DateTime PHP 类?

$value = 'badbadbad';

try {
    $datetime = new \DateTime($value);

    $value = $datetime->format('Y-m-d');
} catch(\Exception $e) {
    // Invalid date
}

如果插入了有效的日期时间字符串,则始终返回您期望的格式。

【讨论】:

    【解决方案5】:

    @baba 发布了更好的解决方案,但发布的代码在某些情况下无法正常工作。

    例如,如果您尝试验证此日期“2019-12-313”;

    $date = date_parse("2019-12-313");
    

    函数返回这个数组:

    Array
    (
        [year] => 2019
        [month] => 12
        [day] => 31
        [hour] => 
        [minute] => 
        [second] => 
        [fraction] => 
        [warning_count] => 0
        [warnings] => Array
            (
            )
    
        [error_count] => 1
        [errors] => Array
            (
                [10] => Unexpected character
            )
    
        [is_localtime] => 
    )
    

    所以,如果你执行命令:

    checkdate($date['month'], $date['day'], $date['year']);
    

    checkdate 将返回一个真值,因为 $date['day'] 的值是 31 而不是 313。

    为避免这种情况,您可能必须对 $date['error_count'] 的值添加检查

    @baba 示例更新

    $date = "2019-12-313";
    $date = date_parse($date); // or date_parse_from_format("d/m/Y", $date);
    if ($date['error_count'] == 0 && checkdate($date['month'], $date['day'], $date['year'])) {
        // Valid Date
    }
    

    【讨论】:

      【解决方案6】:

      您可以使用此功能查看日期:

      function is_date_valid($date, $format = "Y-m-d"){
          $parsed_date = date_parse_from_format($format, $date);
          if(!$parsed_date['error_count'] && !$parsed_date['warning_count']){
              return true;
          }
      
          return false;
      }
      

      使用方法:

      $is_valid = is_date_valid("2021-8-1"); // it will return boolean.
      

      注意:您可以通过在第二个参数中传递格式来更改日期的格式。

      【讨论】:

        【解决方案7】:

        尝试像这样为您的正则表达式设置开始和结束:

        $myregex = "/^\d{2}\/\d{2}\/\d{4}$/";
        

        【讨论】:

          【解决方案8】:
          
          $myregex = "~^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$~";
          
          print filter_var("bad 01/02/2012 bad",FILTER_VALIDATE_REGEXP,array("options"=>array("regexp"=> $myregex)));
          

          【讨论】:

          • 请考虑解释您的代码如何添加到线程中已经存在的 7 个答案
          • 这样你就可以过滤出从 1900-01-01 到 2099-12-31 的确切日期
          【解决方案9】:

          您收到的很多答案表明 RegEx 将允许 99/99/9999 的答案。这可以通过向 RegEx 添加更多内容来解决。如果您知道您永远不会有 1900-2099 年之外的日期...您可以使用这样的 RegEx:

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

          这将验证此格式的日期:dd/mm/YYYY

          之间:01/01/1900 - 31/12/2099

          如果您需要更多年份,只需在接近尾声时添加即可。 |21|22|23|24|25(将延长至 2599 年。)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-02-26
            • 1970-01-01
            • 2010-12-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-01-14
            • 1970-01-01
            相关资源
            最近更新 更多