【问题标题】:php check for a valid date, weird date conversionsphp 检查有效日期,奇怪的日期转换
【发布时间】:2008-09-26 19:05:22
【问题描述】:

有没有办法检查日期/时间是否有效,您会认为这些很容易检查:

$date = '0000-00-00';
$time = '00:00:00';
$dateTime = $date . ' ' . $time;

if(strtotime($dateTime)) {
    // why is this valid?
}

真正让我感动的是:

echo date('Y-m-d', strtotime($date)); 

结果:“1999-11-30”,

嗯?我从 0000-00-00 到 1999-11-30 ???

我知道我可以进行比较以查看日期是否这些值中的任何一个等于我拥有的日期,但这不是一种非常可靠的检查方式。有什么好方法可以检查我是否有一个有效的日期?任何人都有一个很好的功能来检查这个?

编辑: 人们在问我在做什么: 在 Linux localhost 2.6.18-53.1.14.el5 #1 SMP Wed Mar 5 11:36:49 EST 2008 i686 i686 i386 GNU/ 上运行 PHP 5.2.5 (cli)(构建时间:2008 年 7 月 23 日 11:32:27) Linux

【问题讨论】:

  • strtotime("0000-00-00 00:00:00") 在 32 位系统上返回 FALSE。 strtotime("0000-00-00 00:00:00") 在 64 位系统上返回 -62169955200。

标签: php date time strtotime


【解决方案1】:

来自php.net

<?php
function isValidDateTime($dateTime)
{
    if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) {
        if (checkdate($matches[2], $matches[3], $matches[1])) {
            return true;
        }
    }

    return false;
}
?>

【讨论】:

    【解决方案2】:

    这里提到:https://bugs.php.net/bug.php?id=45647

    这里没有bug,00-00-00表示2000-00-00,也就是1999-12-00, 这是 1999 年 11 月 30 日。没有错误,完全正常。

    正如一些测试所示,如果有点不安,向后滚动是预期的行为:

    >> date('Y-m-d', strtotime('2012-03-00'))
    string: '2012-02-29'
    >> date('Y-m-d', strtotime('2012-02-00'))
    string: '2012-01-31'
    >> date('Y-m-d', strtotime('2012-01-00'))
    string: '2011-12-31'
    >> date('Y-m-d', strtotime('2012-00-00'))
    string: '2011-11-30'
    

    【讨论】:

      【解决方案3】:

      回显日期('Y-m-d', strtotime($date));

      结果:“1999-11-30”

      strtotime 的结果是 943920000 - 这是从Unix epoch(测量时间的基准)到 1999-11-30 之间的大致秒数。

      当您尝试前纪元时间(包括“0000-00-00 00:00:00”)时,mktime(), localtime(), strtotime() 上有一个记录的 mysql bug 都返回这个奇数值。关于这是否真的是一个错误,关于链接线程存在一些争论:

      由于时间戳是从 1970 年开始的,我认为它不应该 无论如何工作。

      以下是我用于将上述日期时间转换为时间戳以进行比较等的函数,对于“0000-00-00 00:00:00”以外的日期,这可能对您有用

      /**
       * Converts strings of the format "YYYY-MM-DD HH:MM:SS" into php dates
       */
      function convert_date_string($date_string)
      {
          list($date, $time) = explode(" ", $date_string);
          list($hours, $minutes, $seconds) = explode(":", $time);
          list($year, $month, $day) = explode("-", $date);
          return mktime($hours, $minutes, $seconds, $month, $day, $year);
      }
      

      【讨论】:

      • 我试过 date('Y-m-d', convert_date_string('0000-00-00 00:00:00')) 但仍然给出 1999 年的日期
      • 发现 PHP 错误报告,关于 PHP 中 0000-00.. 值的基于时间的函数的奇怪行为。关于该线程是否真的是一个错误存在一些争论,就好像人们想要计算 1970 年之前的日期一样!
      【解决方案4】:

      当您超出范围时,不要期望获得一致的结果:

      cfstrtotime

      cfGnu Calendar-date-items.html

      "对于数字月份,ISO 8601 允许格式“年-月-日”, 其中 year 是任何正数, 月份是介于 01 之间的数字 和 12,而 day 是 01 到 31 之间的数字。一种 前导零必须存在,如果 数字小于十。”

      所以 '0000-00-00' 给出了奇怪的结果,这是合乎逻辑的!


      “此外,并非全部 平台支持负时间戳, 因此您的日期范围可能是 限于不早于 Unix 时代。这意味着例如 %e、%T、%R 和 %D(可能有 更多)和一月之前的日期 1、1970 不能在 Windows 上运行,有些 Linux 发行版和其他一些 操作系统。”

      cfstrftime


      改用checkdate 函数(更健壮):

      月份: 月份介于 1 和 12 之间

      天: 日期在给定的允许天数内 月。闰年 考虑。

      年份: 年份介于 1 到 32767 之间

      【讨论】:

        【解决方案5】:

        此版本允许字段为空,具有 mm/dd/yy 或 mm/dd/yyyy 格式的日期,允许单个数字小时,添加可选的 am/pm,并更正时间匹配中的一些细微缺陷.

        仍然允许一些病态时间,例如“23:14 AM”。

        function isValidDateTime($dateTime) {
            if (trim($dateTime) == '') {
                return true;
            }
            if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})(\s+(([01]?[0-9])|(2[0-3]))(:[0-5][0-9]){0,2}(\s+(am|pm))?)?$/i', $dateTime, $matches)) {
                list($all,$mm,$dd,$year) = $matches;
                if ($year <= 99) {
                    $year += 2000;
                }
                return checkdate($mm, $dd, $year);
            }
            return false;
        }
        

        【讨论】:

          【解决方案6】:

          如果你只是想处理一个没有时间的 mysql 日期字段的日期转换,你可以像我一样修改这个很棒的代码。 在我的 PHP 版本上没有执行这个功能,我每次都会得到“0000-00-00”。恼人的。

          function ConvertDateString ($DateString)
          {
              list($year, $month, $day) = explode("-", $DateString);
              return date ("Y-m-d, mktime (0, 0, 0, $month, $day, $year));
          }
          

          【讨论】:

            【解决方案7】:
            <?php
            function is_valid_date($user_date=false, $valid_date = "1900-01-01") {
                $user_date = date("Y-m-d H:i:s",strtotime($user_date));
                return strtotime($user_date) >= strtotime($valid_date) ? true : false;
            }
            
            echo is_valid_date("00-00-00") ? 1 : 0;    // return 0
            
            echo is_valid_date("3/5/2011") ? 1 : 0;    // return 1
            

            【讨论】:

            • 这适用于“最近”的日期,但如果我有一个九十年代初的日期,它总是会返回 false
            • @SeanDowney 已编辑,它应该为您的“九十年代初的日期”返回 TRUE。
            【解决方案8】:

            我刚刚更改了上面的马丁答案,它将验证任何类型的日期并以您喜欢的格式返回。

            只需通过编辑以下脚本行来更改格式 strftime("10-10-2012", strtotime($dt));

            <?php
            echo is_date("13/04/10");
            
            function is_date( $str ) {
                $flag = strpos($str, '/');
            
                if(intval($flag)<=0){
                    $stamp = strtotime( $str );
                } else {
                    list($d, $m, $y) = explode('/', $str);    
                    $stamp = strtotime("$d-$m-$y");
                } 
                //var_dump($stamp) ;
            
                if (!is_numeric($stamp)) {
                    //echo "ho" ;
                    return "not a date" ;        
                }
            
                $month = date( 'n', $stamp ); // use n to get date in correct format
                $day   = date( 'd', $stamp );
                $year  = date( 'Y', $stamp );
            
                if (checkdate($month, $day, $year)) {
                    $dt = "$year-$month-$day" ;
                    return strftime("%d-%b-%Y", strtotime($dt));
                    //return TRUE;
                } else {
                    return "not a date" ;
                }
            }
            ?>
            

            【讨论】:

              【解决方案9】:

              我使用以下代码来验证来自 ExtJS 应用程序的日期。

              function check_sql_date_format($date) {
                  $date = substr($date, 0, 10);
                  list($year, $month, $day) = explode('-', $date);
                  if (!is_numeric($year) || !is_numeric($month) || !is_numeric($day)) {
                      return false;
                  }
                  return checkdate($month, $day, $year);
              }
              

              【讨论】:

                【解决方案10】:
                <?php
                
                function is_date( $str ) {
                    $stamp = strtotime( $str );
                
                    if (!is_numeric($stamp)) {
                        return FALSE;
                    }
                    $month = date( 'm', $stamp );
                    $day   = date( 'd', $stamp );
                    $year  = date( 'Y', $stamp );
                
                    if (checkdate($month, $day, $year)) {
                        return TRUE;
                    }
                    return FALSE;
                }
                ?>
                

                【讨论】:

                • 这不适用于某些极端情况,例如 2 月 31 日或 4 月 31 日。例如 date("Y-m-d", strtotime("31.2.2012")) 的结果是 "2012-03-02",即使用户没有输入有效日期,它也会通过 checkdate 验证。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-04-13
                • 1970-01-01
                • 1970-01-01
                • 2012-10-28
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多