【问题标题】:Validate that input is in this time format - "HH:MM" [closed]验证输入是否采用这种时间格式 - “HH:MM”[关闭]
【发布时间】:2011-04-27 06:29:25
【问题描述】:

我正在尝试使用 preg_match 来验证时间输入是否采用这种格式 - “HH:MM”

【问题讨论】:

    标签: php regex validation preg-match


    【解决方案1】:

    您可以使用正则表达式来检查。

    12 小时:

    preg_match("/^(?:1[012]|0[0-9]):[0-5][0-9]$/", $foo)
    

    24 小时:

    preg_match("/^(?:2[0-3]|[01][0-9]):[0-5][0-9]$/", $foo)
    

    如果您使用从 01:0024:59 的 24 小时制,请使用

    preg_match("/^(?:2[0-4]|[01][1-9]|10):([0-5][0-9])$/", $foo)
    

    【讨论】:

    • 抱歉,真的吗?在没有评论的情况下阅读这个是呸。为什么不使用像这样简单的东西:$dateObj = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " .$timeStr); if ($dateObj !== false) { // valid time} else { //invalid time} 但是,是的,为重新发明轮子提供 +14 票
    • @Toskan:我认为这是一个很好的方法。我尝试按照 OP 的要求使用preg_match,尽管我不知道其背后的原因。我知道我以前问过问题,有人告诉我我不应该做我要求做的事情(而不是告诉我该怎么做),这让我很困扰——当然我有理由问为了我想要的。我不知道这张海报的理由是什么:也许他们正在使用 GeSHi 以他们的语言格式化日期,因此 DateTime::createFromFormat 不可用。或者也许他们只是在学习正则表达式。我不知道。
    • @Toskan 我的托管服务已过期,DateTime 对象无法正常工作。
    • 据此 24:59 是有效时间
    • @themis 第三个正则表达式有意允许这样做。前两个故意不允许这样做。
    【解决方案2】:

    验证日期(和/或时间)而不抛出异常的简单函数。它将预期的date format 作为参数:

    function isValidDate(string $date, string $format = 'Y-m-d'): bool
    {
        $dateObj = DateTime::createFromFormat($format, $date);
        return $dateObj && $dateObj->format($format) == $date;
    }
    

    工作原理:它根据传递的$format将输入的日期转换为PHP的DateTime对象,然后将该对象与原始输入日期进行比较。 如果它们匹配,则日期有效并且具有预期的格式。

    一些使用示例:

    /* Valid Examples: */
    isValidDate("2017-05-31");
    isValidDate("23:15:00", 'H:i:s');
    isValidDate("2017-05-31 11:15:00", 'Y-m-d h:i:s');
    
    /* Invalid: */
    isValidDate("2012-00-21");
    isValidDate("25:15:00", 'H:i:s');
    isValidDate("Any string that's not a valid date/time");
    

    【讨论】:

    • 这是最好的。当有官方的 DateTime 类时,我不明白为什么其他人使用正则表达式。你知道为什么?其他一些人花时间,当一个类是官方为一种语言提供的课程时,通常它已经测试了很多次,而且它肯定是通用的,并且考虑到国际问题。特别是当您处理日期和时间时。这些人工作时间,消耗人力和电能。不要两者都浪费,这是一个优秀开发人员的基础;)我知道,这是一项艰巨的任务,但这是正确的
    • 当然,如果您不需要正则表达式,这就是要走的路。
    • 这可以用作简单的真/假检查。返回值为 false 或 dateTime 对象的一个​​实例,所以一个简单的if(DateTime::createFromFormat('H:i',$time)) 对很多情况都有好处。
    • @Snapey 这种方法的主要问题是createFromFormat 接受“愚蠢”的值,例如第 13 个月或第 0 天。日期2000-13-00 将被视为有效,因为它将其解析为 2000- 12-31.
    【解决方案3】:

    假设您要检查的时间是$timeStr,并且根据日期规范必须是H:i 格式。 恕我直言,为此使用正则表达式是愚蠢的。这更容易阅读:

    更新

    $timeStr = " 02:00"; //example of valid time, note whitespace
    test($timeStr);
    $timeStr = "23:59"; //valid
    test($timeStr);
    $timeStr = "24:00"; //invalid
    test($timeStr);
    $timeStr = "25:00"; //invalid
    test($timeStr);    
    $timeStr = "16:61"; // invalid
    test($timeStr);
    
    //tests 23:59 hour format
        function test($timeStr){
    
        $dateObj = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . $timeStr);
    
        if ($dateObj !== false && $dateObj && $dateObj->format('G') == 
            intval($timeStr)){
            //return true;
            echo 'valid  <br/>';
        }
        else{
          //return false;
          echo 'invalid <br/>';
        }
    
    }
    

    【讨论】:

    • 除此之外,25:00 为有效时间。
    • 第二天凌晨 1 点,这是一个功能
    • 创建一个偏移日期并对其进行验证以删除 25:00 之类的输入。 $dateObjOffset = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . '24:00'); if($dateObjOffset
    • @LakshithaUdara 很好的解决方案,如果您希望将 24:00 作为有效时间,我添加了一个更简单的解决方案,直到 23:59 才有效
    • 16:61 也是有效时间。也是一个功能,但可能不是有意的。
    【解决方案4】:

    这是一个检查字符串是否为 00:00 到 23:59 之间的一个小时的代码

    $checked = false;
        if (preg_match('/^\d{2}:\d{2}$/', $str)) {
            if (preg_match("/(2[0-3]|[0][0-9]|1[0-9]):([0-5][0-9])/", $str)) {
                $checked = true;
            }
        }
        var_dump($checked );die;
    

    【讨论】:

    • 匹配 24:15 但不匹配 10:15
    • @Toto - 修正检查
    • 这就是我要找的...谢谢..
    【解决方案5】:

    根据所需格式验证小时、分钟和秒的函数:

    function validTime($time, $format='H:i:s') {
        $d = DateTime::createFromFormat("Y-m-d $format", "2017-12-01 $time");
        return $d && $d->format($format) == $time;
    }
    

    使用方法:

    $valid = validTime("23","H");
    $valid = validTime("23:59","H:i");
    $valid = validTime("23:59:59","H:i:s");
    $valid = validTime("23:59:59");
    

    有效 = 真

    $valid = validTime("25","H");
    $valid = validTime("01:60","H:i");
    $valid = validTime("01:20:61","H:i:s");
    $valid = validTime("01:20:61");
    

    有效 = 假

    【讨论】:

    • 你不需要在那里硬编码“Y-m-d”和“2017-12-01”,它只会让理解更复杂,更不灵活 imo
    • T30说的是实话,我刚测试过。顺便说一句,当有官方的 DateTime 类时,我不明白为什么其他人使用正则表达式。你知道为什么?其他一些人花时间,当一个类是官方为一种语言提供的课程时,通常它已经测试了很多次,而且它肯定是通用的,并且考虑到国际问题。特别是当您处理日期和时间时。这些人工作时间,消耗人力和电能。不要两者都浪费,这是一个优秀开发人员的基础;)我知道,这是一项艰巨的任务,但这是正确的。
    • @Funder 好的软件工程的基础是使用软件工程师知道有效的代码。许多程序员害怕正则表达式的复杂性。理解正则表达式需要真正的承诺。 PHP 是一门很棒的语言,但我遇到了几个 PHP 错误。这就是错误报告的用途。 “通常它已经测试了很多次,而且它肯定是通用的,并且考虑到国际问题。”这就是“我不认识的人总是比我聪明”的谬论。几乎每个 PHP 手册页的描述下方都有错误和问题讨论,包括 DateTime 类。
    • @BlueWater 我想我明白你在说什么。但对我来说,日期和时间是一个很容易出错的话题。有许多格式和规则要知道......正则表达式很复杂,但如果掌握是一个非常有用的工具,我并不是说它们不用于此目的。我指的是 php DateTime 类已有 10 多年的历史,并且已经包含所有 RFC/ISO 标准。为什么要费心重新实现轮子?那么如果出现错误,是否必须报告,所以任何人都将从修复中受益。我认为这个话题始于古希腊;-D
    • “为什么要重新实现轮子?”让车轮变得更好。干杯。
    【解决方案6】:

    你可以这样做:

    if(preg_match('/^(?:[01][0-9]|2[0-3]):[0-5][0-9]$/',$input)) {
            // $input is valid HH:MM format.
    }
    

    【讨论】:

    • 这将允许 24:59。那不是一个有效的时间。此外,你为什么不捕捉小时和分钟?
    • console.log('24:59'.match(/^(?:[01][0-9]|2[0-3]):[0-5][0- 9]$/)) 将输出 null ,此模式不允许 24:59
    【解决方案7】:

    对于可以进行上午和下午的 12 小时比赛,请使用此

    /^(1[0-2]|0?[1-9]):[0-5][0-9] (AM|PM)$/i
    

    它将处理 01:20 am 或 1:20 AM。 上面 12 小时的示例不正确,因为您可能会这样做:

    00:20
    

    这不是有效的 12 小时格式。

    【讨论】:

      【解决方案8】:

      扩展 @Toskan 所写的内容,您可以这样做以 00:00 格式进行验证。如果有效且介于 00:00 和 23:59 之间,则返回 true。

      这也允许使用不同的时间格式...

      function isTimeValid($time_str, $format = 'H:i')
      {
          $DateTime = \DateTime::createFromFormat( "d/m/Y {$format}", "10/10/2010 {$time_str}" );
          return $DateTime && $DateTime->format( "d/m/Y {$format}" ) == "10/10/2010 {$time_str}";
      }
      

      【讨论】:

      • 请检查TILiBRA的答案
      • @Funder 相同的答案,增加了几秒钟。但是,问题是评估 HH:MM,而不是其他任何东西。当然,如果想增加灵活性或将其转换为 isDateTimeValid() 函数,则不需要硬编码...
      • 是的,伙计,但是你可以创建一个像 validateDateTime(string $dateTime, string $format = "H:i") { ..... } 这样的函数,这样你就有一个基本函数默认情况下检查 HH:MM 格式,而您可以传递您想要的另一种有效格式。就像日期,日期+时间,带秒的时间......如果有官方方法可以通过不使用正则表达式来验证日期/时间,这一点很重要。将来,该方法将使用新功能进行更新,而正则表达式将永远保持这种状态。
      • 这是正确的,我知道,如果我不清楚,这就是我试图传达的内容。我也同意没有必要使用正则表达式,这就是为什么我没有在示例中...
      • 你说得对,我指的是其他答案,特别是被接受为解决方案的答案。我不知道为什么没有选择您使用的方法作为正确的解决方案。也许在发布问题时, DateTime 类没有 createFromFormat 方法。我会看看。 编辑: DateTime::createFromFormat 是在 2009 年发布的 v5.3.0 中引入的,比原始问题早一年。 :'(
      【解决方案9】:

      如果您不需要preg_match,这是另一种新颖的方法:

      $thetime = "20:15" // set the time
      $timecheck = explode(":", filter_var($thetime, FILTER_SANITIZE_URL));
      $hourvalid = $minvalid = false;
      if (count($timecheck) > 1 && count($timecheck) < 4) {
         $hourvalid = ((abs(filter_var($timecheck[0], FILTER_SANITIZE_NUMBER_INT)) < 24) 
                      && (abs(filter_var($timecheck[0], FILTER_SANITIZE_NUMBER_INT)) === (INT) $timecheck[0]))
                      ? true : false;
            $minvalid = ((abs(filter_var($timecheck[1], FILTER_SANITIZE_NUMBER_INT)) < 60) 
                      && (abs(filter_var($timecheck[1], FILTER_SANITIZE_NUMBER_INT)) === (INT) $timecheck[1])) 
                      ? true : false;
      }
      
      if ($hourvalid && $minvalid) {//valid time         
         echo $thetime . " is a valid time<br />";
      } else {//invalid time
         echo $thetime . " is NOT a valid time<br />";
      }
      

      可能不是世界上最有效的方法,但它可以做到。仅对从 00:0023:59 的时间有效。此外,8:0 验证为时间(假设您的意思是 08:00)。

      【讨论】:

      • 我不确定不是最高效的,这只是比较和类型检查,这实际上可能是最有效的方式:)(尽管这只是微优化,这是大部分不值得努力):) 另外,我认为不需要FILTER_SANITIZE_URL
      【解决方案10】:

      如果您只想验证 HH:MM 字符串,请更正 @Toskan 的答案

           protected function isValidTime($timeStr){
      
          $dateObj = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . $timeStr);
          $dateObjOffset = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . '24:00');
      
          if($dateObjOffset <= $dateObj){
              return false;
          }
          if ($dateObj !== false) {
             return true;
          }
          else{
             return false;
          }
      }
      

      【讨论】:

        【解决方案11】:

        基于 Charles 用正则表达式的优雅回答。如果您需要对 "HH:MM""H:MM"(即 "9:45"/"09:45")进行单行验证,请使用以下正则表达式来匹配 24 小时格式:

        preg_match("/^(?(?=\d{2})(?:2[0-3]|[01][0-9])|[0-9]):[0-5][0-9]$/", $time)
        

        说明

        (?代表conditional subpattern,语法为:

        (?(条件)是模式|无模式)

        ?= in 条件regexp assertion

        ?: in yes-pattern可选 以获得更好的性能,您可以放弃它。这意味着我们不需要任何 capturing 括号内的 (),我们只需要替代功能。

        所以,我们只描述以下内容:

        1. 如果$time 字符串以两位数字(?=\d{2}) 开头,则使用(2[0-3]|[01][0-9]) 模式来匹配HH 小时表示法("09:45" 大小写)
        2. 否则使用 [0-9] 模式来匹配 H 小时表示法("9:45" 大小写)

        更新

        正如他们所说,简单是天才的姐妹。我们不一定需要上述条件模式。 24 小时 格式的"HH:MM/H:MM" 更简单的验证:

        preg_match("/^(?:2[0-3]|[01][0-9]|[0-9]):[0-5][0-9]$/", $time)
        

        同样,分组括号中的?: () 是禁用捕获的可选选项,您可以删除它。

        因此,在这个正则表达式中,() 的替代子模式试图在第一个 (20..23) 和第二个 (01..19) 模式中匹配两位数小时,然后在最后一个 (@987654346) 模式中匹配一位数@)。

        另外,验证"HH:MM/H:MM"12小时格式:

        preg_match("/^(?:0?[1-9]|1[012]):[0-5][0-9]$/", $time);
        

        在这里,我们尝试将第一个数字 (1..9) 与可能的前零 (0?) 进行匹配,然后再匹配两个数字 (10..12)。

        【讨论】:

          【解决方案12】:

          如果您正在寻找秒数(24 小时)。这对我来说就像一个魅力。

          $time = "23:59:60";    
          preg_match("/^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $time)
          

          【讨论】:

          • 23:59:60 不应是有效时间... :\
          【解决方案13】:

          另一种不使用正则表达式的方法。

          if(is_string($foo)  && (strlen($foo) == 4 || strlen($foo) == 5) && intval(str_replace(':','',$foo)) > -1 && intval(str_replace(':','',$foo)) < 2360){
              stuff to do if valid time
          }
          else{
              stuff to do if invalid time
          }
          

          首先我检查数据类型是否为字符串。如果不是很明显,这不是一个有效时间。然后我检查字符串是否有 4 / 5 个字母的正确长度。 使用 str_replace,我删除了 ':',然后将结果转换为一个整数,我可以轻松地将其与所需的时间范围进行比较(在我的示例中为 00:00 - 23:59)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-10-01
            • 2022-11-03
            • 1970-01-01
            • 2012-09-18
            • 2016-07-28
            • 2011-11-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多