【问题标题】:What can use for DateTime::diff() for PHP 5.2?PHP 5.2 的 DateTime::diff() 有什么用?
【发布时间】:2011-05-01 07:10:50
【问题描述】:

PHP 5.2 中是否有等效于 DateTime::diff() 的函数?

我的本​​地服务器是 PHP 5.3 并使用 DateTime::diff()。然后我发现我的 live 站点使用 PHP 5.2 并给出了错误。

Fatal error: Call to undefined method DateTime::diff() in /var/www/some/other/dir/web/daikon/modules/projects/views/admin/log/admin_log_list.php on line 40

PHP 代码:

 foreach ($logs as $key => $list){
 ...
 // show date in European way dd-mm-yyyy not in MySQL way yyyy-mm-dd
    $newdate =new DateTime($list['date']) ;
    echo "<td class=\"left\" width=\"8%\">".$newdate->format('d-m-Y')."</td>\n";
    $starttime = new DateTime($list['start_time']);
    echo "<td width=\"7%\">".date_format($starttime, 'H:i')."</td>\n";
    $finishtime = new DateTime($list['finish_time']);
    echo "<td width=\"8%\">".date_format($finishtime, 'H:i')."</td>\n";
    $timediff = 0;
    $interval = $starttime->diff($finishtime);
    $hours   = $interval->format('%h');
    $minutes = $interval->format('%i');
    $timediff = $hours * 60 + $minutes;

【问题讨论】:

  • 你为什么不选择一个答案?

标签: php php-5.2


【解决方案1】:

是的,PHP5.2 中没有该功能,这很烦人。

我假设你不能升级到 5.3?你应该调查一下;几乎没有理由不升级;但我假设你不能出于任何原因。

第一个提示:如果您只需要小于 24 小时的 diff,您可以简单地减去两个时间戳,然后执行 $time_diff = date('H:i:s',$subtracted_value);

如果您进行超过 24 小时的差异,但您可以只返回天数和时差,您可以通过对减去的值进行模数计算来扩展上述技术,反对一天的秒数(即24*60*60,即86400)

$subtracted_value = $date1 - $date2;
$days_diff = $subtracted_value % 86400;
$time_diff = date('H:i:s',$subtracted_value);

如果您需要几周时间,当然可以$days_diff % 7

不幸的是,手动技术在几周后就失效了,因为月份和年份的长度是可变的(从技术上讲,天也是,考虑到夏令时,但你可能会忽略这一点,特别是因为你只会是一小时最多),但希望这足以让你开始。

【讨论】:

  • 你不应该只除以 86400,而不是模数吗?
  • @Rocket....嗯,可能。这个答案是不久前的,所以我不记得我在想什么,但你可能是对的。
  • 我意识到这是一个旧答案,但在搜索如何在 PHP 5.2 上使用 DateTime::diff() 后,我在 Google 上找到了它。
【解决方案2】:

阅读 PHP date_diff 页面中的贡献说明 http://us3.php.net/manual/en/function.date-diff.php

【讨论】:

    【解决方案3】:

    Spudley 的答案对我不起作用——从另一个中减去任何 DateTime 会在我的系统上得到 0。

    我能够通过使用带有“U”说明符的 DateTime::format 来使其工作(自 Unix 纪元以来的秒数):

    $start = new DateTime('2010-10-12');
    $end = new DateTime();
    $days = round(($end->format('U') - $start->format('U')) / (60*60*24));
    

    这适用于我的开发系统 (5.3.4) 和我的部署系统 (5.2.11)。

    【讨论】:

    • 几乎完美,除了你使用abs(),它假定它总是积极的。
    • 感谢您指出这一点,@ShivanRaptor。我回顾了我为此编写的代码,它需要一个正值,并且总是将今天与过去的日期进行比较。该代码中的错误是我从开始日期中减去今天,而不是相反,所以我使用abs() 将其转换为正值。如果结束日期早于开始日期,我已经更新了上面的示例以返回负值,这是DateTime::diff() 的默认行为。
    • 我需要在除法的上部添加圆括号:$days = round(($end-&gt;format('U') - $start-&gt;format('U')) / (60*60*24))
    • 这不能正常工作,使用 DateTime::diff() 我得到了 340 天和这个代码 341。不建议在生产中使用它。
    【解决方案4】:

    Spudley 很接近,但您需要使用 gmdate 而不是 date。

    所以这可以工作 24 小时或更短的时间(如果它至少是一个正值):

    $difference = $date2->format('U') - $date1->format('U');
    $time_diff = gmdate('H:i:s',$difference);
    

    【讨论】:

      【解决方案5】:

      PHP 有处理 Unix 时间戳的方法。

      正如其他人所指出的,通过使用自 Unix 日期以来的秒数,计算时间很容易。

      PHP 的 strtotime() 将日期转换为时间戳:

      $diff = round((strtotime($list['start']) - strtotime($list['finish'])) / 86400);
      

      如果要计算到当前时间,time() 提供“现在”的时间戳:

      $diff = round((time() - strtotime($list['date'])) / 86400);
      

      86400 是一天中的秒数。
      如果您希望转换为年份,请使用 31557000,这几乎是 365.24219 * 86400。

      这里的另一个优势是 strtotime 可以采用几乎任何人类可读格式的输入日期,因此在代码中非常容易使用。

      【讨论】:

        【解决方案6】:

        我用这个,好像没问题 - 显然你可以添加第二个参数使其更灵活:

        function GetDateDiffFromNow($originalDate) 
        {
            $unixOriginalDate = strtotime($originalDate);
            $unixNowDate = strtotime('now');
            $difference = $unixNowDate - $unixOriginalDate ;
            $days = (int)($difference / 86400);
            $hours = (int)($difference / 3600);
            $minutes = (int)($difference / 60);
            $seconds = $difference;
        
            // now do what you want with this now and return ...
        }
        

        【讨论】:

          【解决方案7】:

          我试图改进 Christopher Pickslay 的答案。

          我创建了这个函数,它使用原始DateInterval 对象的大部分属性返回和对象。

          没有“days”属性,因为在我的测试服务器中它似乎是some bug(它总是返回 6015)。

          另外,我假设每个月有 30 天,这绝对不准确,但可能会有所帮助。

          function dateTimeDiff($date1, $date2) {
          
              $alt_diff = new stdClass();
              $alt_diff->y =  floor(abs($date1->format('U') - $date2->format('U')) / (60*60*24*365));
              $alt_diff->m =  floor((floor(abs($date1->format('U') - $date2->format('U')) / (60*60*24)) - ($alt_diff->y * 365))/30);
              $alt_diff->d =  floor(floor(abs($date1->format('U') - $date2->format('U')) / (60*60*24)) - ($alt_diff->y * 365) - ($alt_diff->m * 30));
              $alt_diff->h =  floor( floor(abs($date1->format('U') - $date2->format('U')) / (60*60)) - ($alt_diff->y * 365*24) - ($alt_diff->m * 30 * 24 )  - ($alt_diff->d * 24) );
              $alt_diff->i = floor( floor(abs($date1->format('U') - $date2->format('U')) / (60)) - ($alt_diff->y * 365*24*60) - ($alt_diff->m * 30 * 24 *60)  - ($alt_diff->d * 24 * 60) -  ($alt_diff->h * 60) );
              $alt_diff->s =  floor( floor(abs($date1->format('U') - $date2->format('U'))) - ($alt_diff->y * 365*24*60*60) - ($alt_diff->m * 30 * 24 *60*60)  - ($alt_diff->d * 24 * 60*60) -  ($alt_diff->h * 60*60) -  ($alt_diff->i * 60) );
              $alt_diff->invert =  (($date1->format('U') - $date2->format('U')) > 0)? 0 : 1 ;
          
              return $alt_diff;
          }    
          

          【讨论】:

          • 用这个 30 我们可以计算该月的确切天数:cal_days_in_month(CAL_GREGORIAN, 8, 2003);
          【解决方案8】:

          我只是需要它(不幸的是)用于 WordPress 插件。这个我用了2次函数:

          1. 在我的班级中调用 ->diff()(我的班级扩展了 DateTime,所以 $this 是参考日期时间

            function diff ($secondDate){
                $firstDateTimeStamp = $this->format("U");
                $secondDateTimeStamp = $secondDate->format("U");
                $rv = ($secondDateTimeStamp - $firstDateTimeStamp);
                $di = new DateInterval($rv);
                return $di;
            }
            
          2. 然后我重新创建了一个假 DateInterval 类(因为 DateInterval 仅在 PHP >= 5.3 中有效)如下:

            Class DateInterval {
                /* Properties */
                public $y = 0;
                public $m = 0;
                public $d = 0;
                public $h = 0;
                public $i = 0;
                public $s = 0;
            
                /* Methods */
                public function __construct ( $time_to_convert /** in seconds */) {
                    $FULL_YEAR = 60*60*24*365.25;
                    $FULL_MONTH = 60*60*24*(365.25/12);
                    $FULL_DAY = 60*60*24;
                    $FULL_HOUR = 60*60;
                    $FULL_MINUTE = 60;
                    $FULL_SECOND = 1;
            
            //        $time_to_convert = 176559;
                    $seconds = 0;
                    $minutes = 0;
                    $hours = 0;
                    $days = 0;
                    $months = 0;
                    $years = 0;
            
                    while($time_to_convert >= $FULL_YEAR) {
                        $years ++;
                        $time_to_convert = $time_to_convert - $FULL_YEAR;
                    }
            
                    while($time_to_convert >= $FULL_MONTH) {
                        $months ++;
                        $time_to_convert = $time_to_convert - $FULL_MONTH;
                    }
            
                    while($time_to_convert >= $FULL_DAY) {
                        $days ++;
                        $time_to_convert = $time_to_convert - $FULL_DAY;
                    }
            
                    while($time_to_convert >= $FULL_HOUR) {
                        $hours++;
                        $time_to_convert = $time_to_convert - $FULL_HOUR;
                    }
            
                    while($time_to_convert >= $FULL_MINUTE) {
                        $minutes++;
                        $time_to_convert = $time_to_convert - $FULL_MINUTE;
                    }
            
                    $seconds = $time_to_convert; // remaining seconds
                    $this->y = $years;
                    $this->m = $months;
                    $this->d = $days;
                    $this->h = $hours;
                    $this->i = $minutes;
                    $this->s = $seconds;
                }
            }
            

          希望对某人有所帮助。

          【讨论】:

          • 不错,但为什么不使用 mod 函数 (%)(和整数除法)而不是循环获取余数
          【解决方案9】:

          请注意,如果您的 DateTime 对象是从没有任何时区信息的日期字符串创建的(如 mysql 中的“2012-01-01 05:00:00”),则稍后通过 setTimeZone 使用 DateTimeZone 对象设置时区() 不会更改 DateTime 对象的内部时间戳。

          $localtime = new DateTime('2012-01-01 08:00:00+02:00'); // Europe/Copenhagen (+ daylight savings)
          $localtime->setTimezone(new DateTimeZone('UTC')); // convert local time to utc
          
          $utctime = new DateTime('2012-01-01 06:00:00'); // timezone assumed utc, but is in fact unknown
          $utctime->setTimezone(new DateTimeZone('UTC')); // trying to rectify missing timezone which fails, because the internal timestamp isn't modified, although any other format than 'U' may indicate so
          #$utctime = new DateTime('2012-01-01 06:00:00+00:00'); // timezone stated, this works
          
          $diff = intval($localtime->format('U')) - intval($utctime->format('U'));
          echo $diff; // expecting zero
          

          【讨论】:

            【解决方案10】:

            这是您问题的最佳解决方案。

            <?php
            
            /* Find difference between two dates in days. PHP 5.2.x.  */
            
            $d1 = date('Y-m-d', strtotime('2013-06-13'));
            $d2 = date("Y-m-d");
            echo diff($d1, $d2);
            
            function diff($date1, $date2) {
                $diff = abs(strtotime($date2) - strtotime($date1));
                $years = floor($diff / (365*60*60*24));
                $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
                $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24) / (60*60*24));
                return $days;
            }
            ?>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-05-07
              • 2017-03-14
              • 1970-01-01
              • 1970-01-01
              • 2011-07-20
              相关资源
              最近更新 更多