零零乙 2009-03-24 10:33 采纳率: 33.3%
浏览 495
已采纳

如何使用 PHP 计算两个日期之间的差异?

I have two dates of the form:

Start Date: 2007-03-24 
End Date: 2009-06-26

Now I need to find the difference between these two in the following form:

2 years, 3 months and 2 days

How can I do this in PHP?

转载于:https://stackoverflow.com/questions/676824/how-to-calculate-the-difference-between-two-dates-using-php

  • 写回答

30条回答 默认 最新

  • 七度&光 2009-03-24 10:35
    关注

    For PHP < 5.3 otherwise see jurka's answer below

    You can use strtotime() to convert two dates to unix time and then calculate the number of seconds between them. From this it's rather easy to calculate different time periods.

    $date1 = "2007-03-24";
    $date2 = "2009-06-26";
    
    $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));
    
    printf("%d years, %d months, %d days\n", $years, $months, $days);
    

    Edit: Obviously the preferred way of doing this is like described by jurka below. My code is generally only recommended if you don't have PHP 5.3 or better.

    Several people in the comments have pointed out that the code above is only an approximation. I still believe that for most purposes that's fine, since the usage of a range is more to provide a sense of how much time has passed or remains rather than to provide precision - if you want to do that, just output the date.

    Despite all that, I've decided to address the complaints. If you truly need an exact range but haven't got access to PHP 5.3, use the code below (it should work in PHP 4 as well). This is a direct port of the code that PHP uses internally to calculate ranges, with the exception that it doesn't take daylight savings time into account. That means that it's off by an hour at most, but except for that it should be correct.

    <?php
    
    /**
     * Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff()
     * implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved.
     * 
     * See here for original code:
     * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup
     * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup
     */
    
    function _date_range_limit($start, $end, $adj, $a, $b, $result)
    {
        if ($result[$a] < $start) {
            $result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1;
            $result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1);
        }
    
        if ($result[$a] >= $end) {
            $result[$b] += intval($result[$a] / $adj);
            $result[$a] -= $adj * intval($result[$a] / $adj);
        }
    
        return $result;
    }
    
    function _date_range_limit_days($base, $result)
    {
        $days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
        $days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    
        _date_range_limit(1, 13, 12, "m", "y", &$base);
    
        $year = $base["y"];
        $month = $base["m"];
    
        if (!$result["invert"]) {
            while ($result["d"] < 0) {
                $month--;
                if ($month < 1) {
                    $month += 12;
                    $year--;
                }
    
                $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
                $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];
    
                $result["d"] += $days;
                $result["m"]--;
            }
        } else {
            while ($result["d"] < 0) {
                $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
                $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];
    
                $result["d"] += $days;
                $result["m"]--;
    
                $month++;
                if ($month > 12) {
                    $month -= 12;
                    $year++;
                }
            }
        }
    
        return $result;
    }
    
    function _date_normalize($base, $result)
    {
        $result = _date_range_limit(0, 60, 60, "s", "i", $result);
        $result = _date_range_limit(0, 60, 60, "i", "h", $result);
        $result = _date_range_limit(0, 24, 24, "h", "d", $result);
        $result = _date_range_limit(0, 12, 12, "m", "y", $result);
    
        $result = _date_range_limit_days(&$base, &$result);
    
        $result = _date_range_limit(0, 12, 12, "m", "y", $result);
    
        return $result;
    }
    
    /**
     * Accepts two unix timestamps.
     */
    function _date_diff($one, $two)
    {
        $invert = false;
        if ($one > $two) {
            list($one, $two) = array($two, $one);
            $invert = true;
        }
    
        $key = array("y", "m", "d", "h", "i", "s");
        $a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
        $b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));
    
        $result = array();
        $result["y"] = $b["y"] - $a["y"];
        $result["m"] = $b["m"] - $a["m"];
        $result["d"] = $b["d"] - $a["d"];
        $result["h"] = $b["h"] - $a["h"];
        $result["i"] = $b["i"] - $a["i"];
        $result["s"] = $b["s"] - $a["s"];
        $result["invert"] = $invert ? 1 : 0;
        $result["days"] = intval(abs(($one - $two)/86400));
    
        if ($invert) {
            _date_normalize(&$a, &$result);
        } else {
            _date_normalize(&$b, &$result);
        }
    
        return $result;
    }
    
    $date = "1986-11-10 19:37:22";
    
    print_r(_date_diff(strtotime($date), time()));
    print_r(_date_diff(time(), strtotime($date)));
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(29条)

报告相同问题?

悬赏问题

  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上