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

How to calculate the difference between two dates using PHP?

提问人: 提问时间:3/24/2009 最后编辑:Taryn 更新时间:8/11/2023 访问量:1107782

问:

我有两个表格的日期:

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

现在我需要以以下形式找到这两者之间的区别:

2 years, 3 months and 2 days

如何在PHP中做到这一点?

php 日期时间 datediff

评论

3赞 dbasnett 3/24/2009
2 年 94 天。考虑到闰年,计算月份是有问题的。这需要有多准确?
0赞 Cole Tobin 6/26/2014
如何计算相对时间?

答:

592赞 Emil H 3/24/2009 #1

将其用于遗留代码(PHP < 5.3;2009 年 6 月)。有关最新的解决方案,请参阅上面的 jurkas 的回答

您可以使用 strtotime() 将两个日期转换为 unix 时间,然后计算它们之间的秒数。由此可以很容易地计算出不同的时间段。

$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);

编辑:显然,首选的方法是如下 jurka 所描述的。通常只有在您没有 PHP 5.3 或更高版本的情况下才推荐使用我的代码。

评论中有人指出,上面的代码只是一个近似值。我仍然相信,对于大多数目的来说,这很好,因为范围的使用更多的是提供已经过去或剩余的时间的感觉,而不是提供精确度 - 如果你想这样做,只需输出日期。

尽管如此,我还是决定解决这些投诉。如果您确实需要一个确切的范围,但无法访问 PHP 5.3,请使用下面的代码(它也应该适用于 PHP 4)。这是 PHP 内部用于计算范围的代码的直接移植,不同之处在于它不考虑夏令时。这意味着它最多相差一个小时,但除此之外,它应该是正确的。

<?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)));

评论

1赞 Jon Cram 8/7/2009
如果你使用的是 DateTime 类,你可以使用 $date->format('U') 来获取 unix 时间戳。
4赞 Arno 12/21/2009
如果您必须处理夏令时/冬令时,那就不是真的了。在这种特殊情况下,当您调整夏令时/冬令时时,一天等于 23 或 25 小时。
4赞 Emil H 12/22/2009
好吧,闰年也可以提出同样的论点。它也没有考虑到这一点。不过,我不相信你甚至想考虑到这一点,因为我们在这里讨论的是一个范围。范围的语义与绝对日期的语义略有不同。
9赞 enobrev 4/12/2011
此函数不正确。它对近似值有好处,但对于精确范围来说是不正确的。首先,它假设一个月中有 30 天,也就是说,2 月 1 日至 3 月 1 日的天数差与 7 月 1 日至 8 月 1 日的天数差相同(无论闰年如何)。
1赞 Paul Tarjan 3/19/2013
在 PHP 中,引用变量位于函数签名中,而不是调用中。将所有签名移动到签名中。&
6赞 Mark Pim 3/24/2009 #2

您可以使用

getdate()

函数,该函数返回一个数组,其中包含所提供的日期/时间的所有元素:

$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");

如果您的开始日期和结束日期是字符串格式,请使用

$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);

在上述代码之前

评论

0赞 Sirber 7/27/2010
似乎不起作用。我在时间戳时代开始时得到一个日期。
0赞 Salman A 2/21/2012
重要的是要了解您需要做一个才能获得正确的年数。您还需要从 GMT 中减去小时差才能获得正确的时间。您还需要从月份和日期中减去 1。$my_t["year"] -= 1970
5赞 James - Php Development 1/7/2010 #3

我在下一页上找到了您的文章,其中包含许多有关PHP日期时间计算的参考资料。

使用 PHP 计算两个日期(和时间)之间的差值。以下页面提供了一系列不同的方法(总共 7 种),用于使用 PHP 执行日期/时间计算,以确定两个日期之间的时间(小时、时间)、天、月或年之间的差异。

请参阅 PHP 日期时间 – 计算 2 个日期之间差异的 7 种方法

40赞 khaldonno 3/19/2010 #4

查看小时、小齿轮和秒数。.

$date1 = "2008-11-01 22:45:00"; 

$date2 = "2009-12-04 13:44:01"; 

$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));

$hours   = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60)); 

$minuts  = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60); 

$seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60)); 

printf("%d years, %d months, %d days, %d hours, %d minuts\n, %d seconds\n", $years, $months, $days, $hours, $minuts, $seconds); 

评论

9赞 Dolphin 8/5/2011
可能这不会给出准确的结果。
8赞 3/25/2012
这是一个可怕的解决方案,除非您被迫使用非常过时的 PHP 版本......
3赞 Peter Mortensen 4/9/2014
没那么干涩。例如,60*60*24 重复 15 次。复制粘贴重用万岁!
1赞 Peter Mortensen 4/9/2014
闰年呢?一年不是平均 365 天。
1赞 Peter Mortensen 4/9/2014
此代码假定一个月平均为 30 天。即使假设一年有 365 天,平均月份也是 365 / 12 = 30.42 天(大约)。
12赞 Jake Wilson #5

我不知道你是否在使用 PHP 框架,但很多 PHP 框架都有日期/时间库和帮助程序来帮助你重新发明轮子。

例如,CodeIgniter 就有这个函数。只需输入两个 Unix 时间戳,它就会自动生成如下结果:timespan()

1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes

http://codeigniter.com/user_guide/helpers/date_helper.html

1034赞 jurka 10/13/2010 #6

我建议使用 DateTime 和 DateInterval 对象。

$date1 = new DateTime("2007-03-24");
$date2 = new DateTime("2009-06-26");
$interval = $date1->diff($date2);
echo "difference " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days "; 

// shows the total amount of days (not divided into years, months and days like above)
echo "difference " . $interval->days . " days ";

阅读更多 php DateTime::d iff manual

从手册:

从 PHP 5.2.2 [2007 年 5 月] 开始,可以使用比较运算符比较 DateTime 对象。

$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2); // bool(false)
var_dump($date1 < $date2);  // bool(true)
var_dump($date1 > $date2);  // bool(false)

评论

19赞 hakre 8/7/2011
+1 DateTime 可以正确处理闰年和时区,书架上有一本好书:phparch.com/books/......
3赞 potatoe 2/19/2012
有没有一种方法可以给出两个 DateTime 之间的总秒数?(不将组件相加,即)
1赞 jurka 7/18/2012
@Panique $interval->天和$interval->天是不同的衡量标准。您上面的评论是对的“显示总天数(未像上述那样分为年、月和日)”
1赞 Paulo Freitas 8/5/2012
@potatoe 你可能想要.$date2->format('U') - $date1->format('U')
3赞 Pim Schaaf 3/16/2013
请注意,在 Windows 上存在一个错误,即 DateInterval 在某些 PHP 版本上具有不正确的 days 属性(始终为 6015):bugs.php.net/bug.php?id=51184(有关修复/解决方法,请参阅那里的注释)
6赞 esc 10/14/2010 #7
// If you just want to see the year difference then use this function.
// Using the logic I've created you may also create month and day difference
// which I did not provide here so you may have the efforts to use your brain.
// :)
$date1='2009-01-01';
$date2='2010-01-01';
echo getYearDifference ($date1,$date2);
function getYearDifference($date1=strtotime($date1),$date2=strtotime($date2)){
    $year = 0;
    while($date2 > $date1 = strtotime('+1 year', $date1)){
        ++$year;
    }
    return $year;
}

评论

0赞 Peter Mortensen 4/9/2014
“strtotime('+1 year', $date 1)”是否考虑了闰年?
14赞 enobrev 10/18/2010 #8

我投票支持jurka答案,因为这是我的最爱,但我有一个php.5.3之前的版本......

我发现自己正在研究一个类似的问题——这就是我最初回答这个问题的方式——但只是需要几个小时的差异。但是我的函数也很好地解决了这个问题,而且我自己的库中没有任何地方可以保存它不会丢失和遗忘的地方,所以......希望这对某人有用。

/**
 *
 * @param DateTime $oDate1
 * @param DateTime $oDate2
 * @return array 
 */
function date_diff_array(DateTime $oDate1, DateTime $oDate2) {
    $aIntervals = array(
        'year'   => 0,
        'month'  => 0,
        'week'   => 0,
        'day'    => 0,
        'hour'   => 0,
        'minute' => 0,
        'second' => 0,
    );

    foreach($aIntervals as $sInterval => &$iInterval) {
        while($oDate1 <= $oDate2){ 
            $oDate1->modify('+1 ' . $sInterval);
            if ($oDate1 > $oDate2) {
                $oDate1->modify('-1 ' . $sInterval);
                break;
            } else {
                $iInterval++;
            }
        }
    }

    return $aIntervals;
}

和测试:

$oDate = new DateTime();
$oDate->modify('+111402189 seconds');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));

结果:

object(DateTime)[2]
  public 'date' => string '2014-04-29 18:52:51' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'America/New_York' (length=16)

array
  'year'   => int 3
  'month'  => int 6
  'week'   => int 1
  'day'    => int 4
  'hour'   => int 9
  'minute' => int 3
  'second' => int 8

我从这里得到了最初的想法,我修改了它以供我使用(我希望我的修改也会显示在该页面上)。

你可以很容易地删除你不需要的间隔(比如“周”),方法是从数组中删除它们,或者添加一个参数,或者只是在输出字符串时过滤掉它们。$aIntervals$aExclude

评论

0赞 Stephen Harris 8/18/2012
不幸的是,由于年份/月份溢出,这不会返回与 DateInterval 相同的内容。
2赞 Alix Axel 11/2/2012
@StephenHarris:我还没有测试过这个,但通过阅读代码,我非常有信心它应该返回相同的结果 - 前提是您删除索引(因为从未使用它)。week$aIntervalsDateDiff
0赞 betweenbrain 10/19/2019
这是查找两个日期之间每个间隔发生的日期的绝佳解决方案。
2赞 Konstantin Shegunov 1/11/2011 #9

当 PHP 5.3(分别为 date_diff())不可用时,我正在使用我编写的以下函数:

        function dateDifference($startDate, $endDate)
        {
            $startDate = strtotime($startDate);
            $endDate = strtotime($endDate);
            if ($startDate === false || $startDate < 0 || $endDate === false || $endDate < 0 || $startDate > $endDate)
                return false;

            $years = date('Y', $endDate) - date('Y', $startDate);

            $endMonth = date('m', $endDate);
            $startMonth = date('m', $startDate);

            // Calculate months
            $months = $endMonth - $startMonth;
            if ($months <= 0)  {
                $months += 12;
                $years--;
            }
            if ($years < 0)
                return false;

            // Calculate the days
            $measure = ($months == 1) ? 'month' : 'months';
            $days = $endDate - strtotime('+' . $months . ' ' . $measure, $startDate);
            $days = date('z', $days);   

            return array($years, $months, $days);
        }
15赞 vengat 2/18/2011 #10
<?php
    $today = strtotime("2011-02-03 00:00:00");
    $myBirthDate = strtotime("1964-10-30 00:00:00");
    printf("Days since my birthday: ", ($today - $myBirthDate)/60/60/24);
?>

评论

1赞 Peter Mortensen 4/9/2014
该问题要求将差额作为数、数和数。这将差值输出为总天数。
21赞 casper123 7/25/2011 #11

请看以下链接。这是我迄今为止找到的最好的答案。:)

function dateDiff ($d1, $d2) {

    // Return the number of days between the two dates:    
    return round(abs(strtotime($d1) - strtotime($d2))/86400);

} // end function dateDiff

当您传入 日期参数。该函数使用 PHP ABS() 绝对值来 始终返回一个正数作为两者之间的天数 日期。

请记住,两个日期之间的天数不是 包括两个日期。因此,如果您正在寻找天数 由输入的日期之间的所有日期(包括输入的日期)表示, 您需要将一 (1) 添加到此函数的结果中。

例如,差值(如上述函数返回的) 在2013-02-09和2013-02-14之间是5。但是天数或 日期范围 2013-02-09 - 2013-02-14 表示的日期为 6。

http://www.bizinfosys.com/php/date-difference.html

评论

1赞 Peter Mortensen 4/9/2014
该问题要求将差异视为年数、月数和天数,而不是总天数。
1赞 Aman Deep 1/5/2021
很棒的人,为我工作了几天,谢谢
6赞 Hardik Raval 12/13/2011 #12

我有一些简单的逻辑:

<?php
    per_days_diff('2011-12-12','2011-12-29')
    function per_days_diff($start_date, $end_date) {
        $per_days = 0;
        $noOfWeek = 0;
        $noOfWeekEnd = 0;
        $highSeason=array("7", "8");

        $current_date = strtotime($start_date);
        $current_date += (24 * 3600);
        $end_date = strtotime($end_date);

        $seassion = (in_array(date('m', $current_date), $highSeason))?"2":"1";

        $noOfdays = array('');

        while ($current_date <= $end_date) {
            if ($current_date <= $end_date) {
                $date = date('N', $current_date);
                array_push($noOfdays,$date);
                $current_date = strtotime('+1 day', $current_date);
            }
        }

        $finalDays = array_shift($noOfdays);
        //print_r($noOfdays);
        $weekFirst = array("week"=>array(),"weekEnd"=>array());
        for($i = 0; $i < count($noOfdays); $i++)
        {
            if ($noOfdays[$i] == 1)
            {
                //echo "This is week";
                //echo "<br/>";
                if($noOfdays[$i+6]==7)
                {
                    $noOfWeek++;
                    $i=$i+6;
                }
                else
                {
                    $per_days++;
                }
                //array_push($weekFirst["week"],$day);
            }
            else if($noOfdays[$i]==5)
            {
                //echo "This is weekend";
                //echo "<br/>";
                if($noOfdays[$i+2] ==7)
                {
                    $noOfWeekEnd++;
                    $i = $i+2;
                }
                else
                {
                    $per_days++;
                }
                //echo "After weekend value:- ".$i;
                //echo "<br/>";
            }
            else
            {
                $per_days++;
            }
        }

        /*echo $noOfWeek;
          echo "<br/>";
          echo $noOfWeekEnd;
          echo "<br/>";
          print_r($per_days);
          echo "<br/>";
          print_r($weekFirst);
        */

        $duration = array("weeks"=>$noOfWeek, "weekends"=>$noOfWeekEnd, "perDay"=>$per_days, "seassion"=>$seassion);
        return $duration;
      ?>

评论

0赞 Peter Mortensen 4/9/2014
示例代码的末尾似乎缺少一些东西(结束大括号和“?>”?
1赞 Madjosz 2/13/2018
“简单”的逻辑。这些代码至少是 40 行纯代码。
3赞 GajendraSinghParihar 9/20/2012 #13

前段时间我写了一个函数,因为它提供了许多关于你想要如何约会的选项format_date

function format_date($date, $type, $seperator="-")
{
    if($date)
    {
        $day = date("j", strtotime($date));
        $month = date("n", strtotime($date));
        $year = date("Y", strtotime($date));
        $hour = date("H", strtotime($date));
        $min = date("i", strtotime($date));
        $sec = date("s", strtotime($date));

        switch($type)
        {
            case 0:  $date = date("Y".$seperator."m".$seperator."d",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 1:  $date = date("D, F j, Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 2:  $date = date("d".$seperator."m".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 3:  $date = date("d".$seperator."M".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 4:  $date = date("d".$seperator."M".$seperator."Y h:i A",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 5:  $date = date("m".$seperator."d".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 6:  $date = date("M",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 7:  $date = date("Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 8:  $date = date("j",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 9:  $date = date("n",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 10: 
                     $diff = abs(strtotime($date) - strtotime(date("Y-m-d h:i:s"))); 
                     $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));
                     $date = $years . " years, " . $months . " months, " . $days . "days";
        }
    }
    return($date);
}    

评论

2赞 Peter Mortensen 4/9/2014
这个答案和哈尔多诺的答案一样错误。它假设(案例 10)一年有 365 天(每四年有 366 天(公历的 100 年/400 年规则除外)),一个月有 30 天(非闰年约为 30.42 天)。即使有更好的常数,它也只是平均正确的,对于任何两个特定日期都不一定正确。
2赞 Alix Axel 11/4/2012 #14

DateInterval很棒,但它有几个注意事项:

  1. 仅适用于 PHP 5.3+(但这真的不再是一个很好的借口)
  2. 仅支持年、月、日、时、分、秒(无周)
  3. 它计算上述所有 + 天的差额(您不能仅以月为单位获得差额)

为了克服这个问题,我编写了以下内容(根据@enobrev答案进行了改进):

function date_dif($since, $until, $keys = 'year|month|week|day|hour|minute|second')
{
    $date = array_map('strtotime', array($since, $until));

    if ((count($date = array_filter($date, 'is_int')) == 2) && (sort($date) === true))
    {
        $result = array_fill_keys(explode('|', $keys), 0);

        foreach (preg_grep('~^(?:year|month)~i', $result) as $key => $value)
        {
            while ($date[1] >= strtotime(sprintf('+%u %s', $value + 1, $key), $date[0]))
            {
                ++$value;
            }

            $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]);
        }

        foreach (preg_grep('~^(?:year|month)~i', $result, PREG_GREP_INVERT) as $key => $value)
        {
            if (($value = intval(abs($date[0] - $date[1]) / strtotime(sprintf('%u %s', 1, $key), 0))) > 0)
            {
                $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]);
            }
        }

        return $result;
    }

    return false;
}

它运行两个循环;第一个通过蛮力处理相对间隔(年和月),第二个通过简单的算术计算额外的绝对间隔(所以更快):

echo humanize(date_dif('2007-03-24', '2009-07-31', 'second')); // 74300400 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'minute|second')); // 1238400 minutes, 0 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'hour|minute|second')); // 20640 hours, 0 minutes, 0 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|day')); // 2 years, 129 days
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week')); // 2 years, 18 weeks
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week|day')); // 2 years, 18 weeks, 3 days
echo humanize(date_dif('2007-03-24', '2009-07-31')); // 2 years, 4 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds

function humanize($array)
{
    $result = array();

    foreach ($array as $key => $value)
    {
        $result[$key] = $value . ' ' . $key;

        if ($value != 1)
        {
            $result[$key] .= 's';
        }
    }

    return implode(', ', $result);
}

评论

0赞 Alix Axel 4/9/2014
@PeterMortensen:它应该可以工作,但我不做任何保证。设置您的时区并试一试。
88赞 Madara's Ghost 11/30/2012 #15

最好的做法是使用 PHP 的 DateTime(和 DateInterval)对象。每个日期都封装在一个对象中,然后可以在两者之间做出差异:DateTime

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

该对象将接受任何格式。如果需要更具体的日期格式,可以使用 DateTime::createFromFormat() 创建对象。DateTimestrtotime()DateTime

实例化两个对象后,使用 DateTime::d iff() 从另一个对象中减去一个对象。

$difference = $first_date->diff($second_date);

$difference现在保存一个包含差异信息的 DateInterval 对象。A 如下所示:var_dump()

object(DateInterval)
  public 'y' => int 0
  public 'm' => int 0
  public 'd' => int 20
  public 'h' => int 6
  public 'i' => int 56
  public 's' => int 30
  public 'invert' => int 0
  public 'days' => int 20

要格式化对象,我们需要检查每个值,如果它为 0,则将其排除:DateInterval

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) {
    $result = "";
    if ($interval->y) { $result .= $interval->format("%y years "); }
    if ($interval->m) { $result .= $interval->format("%m months "); }
    if ($interval->d) { $result .= $interval->format("%d days "); }
    if ($interval->h) { $result .= $interval->format("%h hours "); }
    if ($interval->i) { $result .= $interval->format("%i minutes "); }
    if ($interval->s) { $result .= $interval->format("%s seconds "); }

    return $result;
}

现在剩下的就是在对象上调用我们的函数:$differenceDateInterval

echo format_interval($difference);

我们得到了正确的结果:

20 天 6 小时 56 分 30 秒

用于实现目标的完整代码:

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) {
    $result = "";
    if ($interval->y) { $result .= $interval->format("%y years "); }
    if ($interval->m) { $result .= $interval->format("%m months "); }
    if ($interval->d) { $result .= $interval->format("%d days "); }
    if ($interval->h) { $result .= $interval->format("%h hours "); }
    if ($interval->i) { $result .= $interval->format("%i minutes "); }
    if ($interval->s) { $result .= $interval->format("%s seconds "); }

    return $result;
}

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

$difference = $first_date->diff($second_date);

echo format_interval($difference);

评论

0赞 Madara's Ghost 7/23/2013
DateTime()它不是一个函数,而是一个对象,它从 PHP 5.2 开始就存在了。确保您的服务器支持它。
2赞 PhoneixS 7/7/2014
@SecondRikudo DateTime::D iff 需要 PHP 5.3.0
0赞 EgoistDeveloper 9/22/2017
我们有一个问题,交换first_date second_date,我们得到同样的结果?为什么不说 0 天、0 小时、0 分钟、0 秒或只有 0。示例:2012-11-30 17:03:30 - 2012-12-21 00:00:00 和 2012-12-21 00:00:00 - 2012-11-30 17:03:30 得到相同的结果。
0赞 Madara's Ghost 9/23/2017
因为 diff 为您提供了两次之间的差异。无论哪个日期更晚,差异都不是 0。
1赞 nickhar 1/4/2019
这是一个非常好的答案,因为它提供了一个清晰的函数,可以从代码库中的任何位置调用,而无需花费大量时间进行计算。其他答案允许您即时丢弃解决症状而不是解决问题的回声计算......我添加的唯一元素(几乎所有其他帖子都没有涵盖这一点)是 $interval 元素的复数化(如果超过 1)。
5赞 Anuj 12/9/2012 #16

简单的功能

function time_difference($time_1, $time_2, $limit = null)
{

    $val_1 = new DateTime($time_1);
    $val_2 = new DateTime($time_2);

    $interval = $val_1->diff($val_2);

    $output = array(
        "year" => $interval->y,
        "month" => $interval->m,
        "day" => $interval->d,
        "hour" => $interval->h,
        "minute" => $interval->i,
        "second" => $interval->s
    );

    $return = "";
    foreach ($output AS $key => $value) {

        if ($value == 1)
            $return .= $value . " " . $key . " ";
        elseif ($value >= 1)
            $return .= $value . " " . $key . "s ";

        if ($key == $limit)
            return trim($return);
    }
    return trim($return);
}

使用喜欢

echo time_difference ($time_1, $time_2, "day");

会像2 years 8 months 2 days

4赞 Rikin Adhyapak 3/7/2013 #17

您还可以使用以下代码通过四舍五入分数返回日期差异 $date 1 = $duedate;指定截止日期 echo $date 2 = date(“Y-m-d”);当前日期 $ts 1 = strtotime($date 1); $ts 2 = strtotime($date 2); $seconds_diff = $ts 1 - $ts 2; 回声 $datediff = ceil(($seconds_diff/3600)/24);几天后退货

如果您使用 php 的 floor 方法而不是 ceil,它将返回您向下的四舍五入分数。请在此处检查差异,有时如果您的暂存服务器时区与实时站点时区不同,在这种情况下,您可能会得到不同的结果,因此请相应地更改条件。

2赞 3 revsuser2169219 #18

一分钱,一磅: 我刚刚回顾了几个解决方案,它们都提供了一个使用 floor() 的复杂解决方案,然后四舍五入为 26 年 12 个月零 2 天的解决方案,本应是 25 年零 11 个月零 20 天!!!

这是我对这个问题的版本: 可能不优雅,可能编码不好,但如果你不计算闰年,它提供了更接近答案的答案,显然闰年可以编码到这个中,但在这种情况下 - 正如其他人所说,也许你可以提供这个答案: 我已经包含了所有测试条件和print_r,以便您可以更清楚地看到结果的构造: 来了,

设置输入日期/变量:

$ISOstartDate   = "1987-06-22";
$ISOtodaysDate = "2013-06-22";

我们需要将 ISO yyyy-mm-dd 格式分解为 yyyy mm dd,如下所示:

$yDate[ ] = explode('-', $ISOstartDate); print_r($yDate);

$zDate[ ] = explode('-', $ISOtodaysDate); print_r($zDate);

// Lets Sort of the Years!
// Lets Sort out the difference in YEARS between startDate and todaysDate ::
$years = $zDate[0][0] - $yDate[0][0];

// We need to collaborate if the month = month = 0, is before or after the Years Anniversary ie 11 months 22 days or 0 months 10 days...
if ($months == 0 and $zDate[0][1] > $ydate[0][1]) {
    $years = $years -1;
}
// TEST result
echo "\nCurrent years => ".$years;

// Lets Sort out the difference in MONTHS between startDate and todaysDate ::
$months = $zDate[0][1] - $yDate[0][1];

// TEST result
echo "\nCurrent months => ".$months;

// Now how many DAYS has there been - this assumes that there is NO LEAP years, so the calculation is APPROXIMATE not 100%
// Lets cross reference the startDates Month = how many days are there in each month IF m-m = 0 which is a years anniversary
// We will use a switch to check the number of days between each month so we can calculate days before and after the years anniversary

switch ($yDate[0][1]){
    case 01:    $monthDays = '31';  break;  // Jan
    case 02:    $monthDays = '28';  break;  // Feb
    case 03:    $monthDays = '31';  break;  // Mar
    case 04:    $monthDays = '30';  break;  // Apr
    case 05:    $monthDays = '31';  break;  // May
    case 06:    $monthDays = '30';  break;  // Jun
    case 07:    $monthDays = '31';  break;  // Jul
    case 08:    $monthDays = '31';  break;  // Aug
    case 09:    $monthDays = '30';  break;  // Sept
    case 10:    $monthDays = '31';  break;  // Oct
    case 11:    $monthDays = '30';  break;  // Nov
    case 12:    $monthDays = '31';  break;  // Dec
};
// TEST return
echo "\nDays in start month ".$yDate[0][1]." => ".$monthDays;


// Lets correct the problem with 0 Months - is it 11 months + days, or 0 months +days???

$days = $zDate[0][2] - $yDate[0][2] +$monthDays;
echo "\nCurrent days => ".$days."\n";

// Lets now Correct the months to being either 11 or 0 Months, depending upon being + or - the years Anniversary date 
// At the same time build in error correction for Anniversary dates not being 1yr 0m 31d... see if ($days == $monthDays )
if($days < $monthDays && $months == 0)
    {
    $months = 11;       // If Before the years anniversary date
    }
else    {
    $months = 0;        // If After the years anniversary date
    $years = $years+1;  // Add +1 to year
    $days = $days-$monthDays;   // Need to correct days to how many days after anniversary date
    };
// Day correction for Anniversary dates
if ($days == $monthDays )   // if todays date = the Anniversary DATE! set days to ZERO
    {
    $days = 0;          // days set toZERO so 1 years 0 months 0 days
    };

    echo "\nTherefore, the number of years/ months/ days/ \nbetween start and todays date::\n\n";

    printf("%d years, %d months, %d days\n", $years, $months, $days);

最终结果是: 26 年, 0 月, 0 天

这就是我在2013年6月22日经营的时间 - 哎哟!

4赞 liza 6/17/2013 #19
$date1 = date_create('2007-03-24');
$date2 = date_create('2009-06-26');
$interval = date_diff($date1, $date2);
echo "difference : " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days ";
6赞 David Bélanger 8/9/2013 #20

这是我的职能。必需的 PHP >= 5.3.4。它使用 DateTime 类。非常快,很快,可以区分两个日期,甚至是所谓的“时间”。

if(function_exists('grk_Datetime_Since') === FALSE){
    function grk_Datetime_Since($From, $To='', $Prefix='', $Suffix=' ago', $Words=array()){
        #   Est-ce qu'on calcul jusqu'à un moment précis ? Probablement pas, on utilise maintenant
        if(empty($To) === TRUE){
            $To = time();
        }

        #   On va s'assurer que $From est numérique
        if(is_int($From) === FALSE){
            $From = strtotime($From);
        };

        #   On va s'assurer que $To est numérique
        if(is_int($To) === FALSE){
            $To = strtotime($To);
        }

        #   On a une erreur ?
        if($From === FALSE OR $From === -1 OR $To === FALSE OR $To === -1){
            return FALSE;
        }

        #   On va créer deux objets de date
        $From = new DateTime(@date('Y-m-d H:i:s', $From), new DateTimeZone('GMT'));
        $To   = new DateTime(@date('Y-m-d H:i:s', $To), new DateTimeZone('GMT'));

        #   On va calculer la différence entre $From et $To
        if(($Diff = $From->diff($To)) === FALSE){
            return FALSE;
        }

        #   On va merger le tableau des noms (par défaut, anglais)
        $Words = array_merge(array(
            'year'      => 'year',
            'years'     => 'years',
            'month'     => 'month',
            'months'    => 'months',
            'week'      => 'week',
            'weeks'     => 'weeks',
            'day'       => 'day',
            'days'      => 'days',
            'hour'      => 'hour',
            'hours'     => 'hours',
            'minute'    => 'minute',
            'minutes'   => 'minutes',
            'second'    => 'second',
            'seconds'   => 'seconds'
        ), $Words);

        #   On va créer la chaîne maintenant
        if($Diff->y > 1){
            $Text = $Diff->y.' '.$Words['years'];
        } elseif($Diff->y == 1){
            $Text = '1 '.$Words['year'];
        } elseif($Diff->m > 1){
            $Text = $Diff->m.' '.$Words['months'];
        } elseif($Diff->m == 1){
            $Text = '1 '.$Words['month'];
        } elseif($Diff->d > 7){
            $Text = ceil($Diff->d/7).' '.$Words['weeks'];
        } elseif($Diff->d == 7){
            $Text = '1 '.$Words['week'];
        } elseif($Diff->d > 1){
            $Text = $Diff->d.' '.$Words['days'];
        } elseif($Diff->d == 1){
            $Text = '1 '.$Words['day'];
        } elseif($Diff->h > 1){
            $Text = $Diff->h.' '.$Words['hours'];
        } elseif($Diff->h == 1){
            $Text = '1 '.$Words['hour'];
        } elseif($Diff->i > 1){
            $Text = $Diff->i.' '.$Words['minutes'];
        } elseif($Diff->i == 1){
            $Text = '1 '.$Words['minute'];
        } elseif($Diff->s > 1){
            $Text = $Diff->s.' '.$Words['seconds'];
        } else {
            $Text = '1 '.$Words['second'];
        }

        return $Prefix.$Text.$Suffix;
    }
}
8赞 Glavić 9/18/2013 #21

使用示例:

echo time_diff_string('2013-05-01 00:22:35', 'now');
echo time_diff_string('2013-05-01 00:22:35', 'now', true);

输出:

4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago

功能:

function time_diff_string($from, $to, $full = false) {
    $from = new DateTime($from);
    $to = new DateTime($to);
    $diff = $to->diff($from);

    $diff->w = floor($diff->d / 7);
    $diff->d -= $diff->w * 7;

    $string = array(
        'y' => 'year',
        'm' => 'month',
        'w' => 'week',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    );
    foreach ($string as $k => &$v) {
        if ($diff->$k) {
            $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
        } else {
            unset($string[$k]);
        }
    }

    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . ' ago' : 'just now';
}

评论

0赞 Ofir Attia 2/19/2014
如果我想确定差异是否大于 30 分钟,我该怎么办?
0赞 Glavić 2/19/2014
@OfirAttia:你在SO上有一堆这样的问题,只需使用搜索即可。简单演示
5赞 jerdiggity 11/3/2013 #22

这将尝试检测是否给定了时间戳,并将未来的日期/时间作为负值返回:

<?php

function time_diff($start, $end = NULL, $convert_to_timestamp = FALSE) {
  // If $convert_to_timestamp is not explicitly set to TRUE,
  // check to see if it was accidental:
  if ($convert_to_timestamp || !is_numeric($start)) {
    // If $convert_to_timestamp is TRUE, convert to timestamp:
    $timestamp_start = strtotime($start);
  }
  else {
    // Otherwise, leave it as a timestamp:
    $timestamp_start = $start;
  }
  // Same as above, but make sure $end has actually been overridden with a non-null,
  // non-empty, non-numeric value:
  if (!is_null($end) && (!empty($end) && !is_numeric($end))) {
    $timestamp_end = strtotime($end);
  }
  else {
    // If $end is NULL or empty and non-numeric value, assume the end time desired
    // is the current time (useful for age, etc):
    $timestamp_end = time();
  }
  // Regardless, set the start and end times to an integer:
  $start_time = (int) $timestamp_start;
  $end_time = (int) $timestamp_end;

  // Assign these values as the params for $then and $now:
  $start_time_var = 'start_time';
  $end_time_var = 'end_time';
  // Use this to determine if the output is positive (time passed) or negative (future):
  $pos_neg = 1;

  // If the end time is at a later time than the start time, do the opposite:
  if ($end_time <= $start_time) {
    $start_time_var = 'end_time';
    $end_time_var = 'start_time';
    $pos_neg = -1;
  }

  // Convert everything to the proper format, and do some math:
  $then = new DateTime(date('Y-m-d H:i:s', $$start_time_var));
  $now = new DateTime(date('Y-m-d H:i:s', $$end_time_var));

  $years_then = $then->format('Y');
  $years_now = $now->format('Y');
  $years = $years_now - $years_then;

  $months_then = $then->format('m');
  $months_now = $now->format('m');
  $months = $months_now - $months_then;

  $days_then = $then->format('d');
  $days_now = $now->format('d');
  $days = $days_now - $days_then;

  $hours_then = $then->format('H');
  $hours_now = $now->format('H');
  $hours = $hours_now - $hours_then;

  $minutes_then = $then->format('i');
  $minutes_now = $now->format('i');
  $minutes = $minutes_now - $minutes_then;

  $seconds_then = $then->format('s');
  $seconds_now = $now->format('s');
  $seconds = $seconds_now - $seconds_then;

  if ($seconds < 0) {
    $minutes -= 1;
    $seconds += 60;
  }
  if ($minutes < 0) {
    $hours -= 1;
    $minutes += 60;
  }
  if ($hours < 0) {
    $days -= 1;
    $hours += 24;
  }
  $months_last = $months_now - 1;
  if ($months_now == 1) {
    $years_now -= 1;
    $months_last = 12;
  }

  // "Thirty days hath September, April, June, and November" ;)
  if ($months_last == 9 || $months_last == 4 || $months_last == 6 || $months_last == 11) {
    $days_last_month = 30;
  }
  else if ($months_last == 2) {
    // Factor in leap years:
    if (($years_now % 4) == 0) {
      $days_last_month = 29;
    }
    else {
      $days_last_month = 28;
    }
  }
  else {
    $days_last_month = 31;
  }
  if ($days < 0) {
    $months -= 1;
    $days += $days_last_month;
  }
  if ($months < 0) {
    $years -= 1;
    $months += 12;
  }

  // Finally, multiply each value by either 1 (in which case it will stay the same),
  // or by -1 (in which case it will become negative, for future dates).
  // Note: 0 * 1 == 0 * -1 == 0
  $out = new stdClass;
  $out->years = (int) $years * $pos_neg;
  $out->months = (int) $months * $pos_neg;
  $out->days = (int) $days * $pos_neg;
  $out->hours = (int) $hours * $pos_neg;
  $out->minutes = (int) $minutes * $pos_neg;
  $out->seconds = (int) $seconds * $pos_neg;
  return $out;
}

用法示例:

<?php
  $birthday = 'June 2, 1971';
  $check_age_for_this_date = 'June 3, 1999 8:53pm';
  $age = time_diff($birthday, $check_age_for_this_date)->years;
  print $age;// 28

艺术

<?php
  $christmas_2020 = 'December 25, 2020';
  $countdown = time_diff($christmas_2020);
  print_r($countdown);
3赞 Klemen Tusar 11/14/2013 #23

我在 PHP 5.2 中遇到了同样的问题,并用 MySQL 解决了它。可能不完全是你要找的,但这可以解决问题并返回天数:

$datediff_q = $dbh->prepare("SELECT DATEDIFF(:date2, :date1)");
$datediff_q->bindValue(':date1', '2007-03-24', PDO::PARAM_STR);
$datediff_q->bindValue(':date2', '2009-06-26', PDO::PARAM_STR);
$datediff = ($datediff_q->execute()) ? $datediff_q->fetchColumn(0) : false;

更多信息请点击这里 http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff

3赞 ChrisV 1/20/2014 #24

由于每个人都在发布代码示例,因此这里是另一个版本。

我想要一个函数来显示从秒到年的差异(只有一个单位)。对于超过 1 天的时间段,我希望它在午夜滚动(周一上午 10 点到周三上午 9 点看到的是 2 天前,而不是 1 天前)。对于超过一个月的时间段,我希望展期在当月的同一天(包括 30/31 天的月份和闰年)。

这是我想出的:

/**
 * Returns how long ago something happened in the past, showing it
 * as n seconds / minutes / hours / days / weeks / months / years ago.
 *
 * For periods over a day, it rolls over at midnight (so doesn't depend
 * on current time of day), and it correctly accounts for month-lengths
 * and leap-years (months and years rollover on current day of month).
 *
 * $param string $timestamp in DateTime format
 * $return string description of interval
 */
function ago($timestamp)
{
    $then = date_create($timestamp);

    // for anything over 1 day, make it rollover on midnight
    $today = date_create('tomorrow'); // ie end of today
    $diff = date_diff($then, $today);

    if ($diff->y > 0) return $diff->y.' year'.($diff->y>1?'s':'').' ago';
    if ($diff->m > 0) return $diff->m.' month'.($diff->m>1?'s':'').' ago';
    $diffW = floor($diff->d / 7);
    if ($diffW > 0) return $diffW.' week'.($diffW>1?'s':'').' ago';
    if ($diff->d > 1) return $diff->d.' day'.($diff->d>1?'s':'').' ago';

    // for anything less than 1 day, base it off 'now'
    $now = date_create();
    $diff = date_diff($then, $now);

    if ($diff->d > 0) return 'yesterday';
    if ($diff->h > 0) return $diff->h.' hour'.($diff->h>1?'s':'').' ago';
    if ($diff->i > 0) return $diff->i.' minute'.($diff->i>1?'s':'').' ago';
    return $diff->s.' second'.($diff->s==1?'':'s').' ago';
}
5赞 ElasticThoughts 3/31/2014 #25

“如果”日期存储在MySQL中,我发现在数据库级别进行差异计算更容易......然后根据日、小时、分钟、秒输出,根据需要解析和显示结果......

mysql> select firstName, convert_tz(loginDate, '+00:00', '-04:00') as loginDate, TIMESTAMPDIFF(DAY, loginDate, now()) as 'Day', TIMESTAMPDIFF(HOUR, loginDate, now())+4 as 'Hour', TIMESTAMPDIFF(MINUTE, loginDate, now())+(60*4) as 'Min', TIMESTAMPDIFF(SECOND, loginDate, now())+(60*60*4) as 'Sec' from User_ where userId != '10158' AND userId != '10198' group by emailAddress order by loginDate desc;
 +-----------+---------------------+------+------+------+--------+
 | firstName | loginDate           | Day  | Hour | Min  | Sec    |
 +-----------+---------------------+------+------+------+--------+
 | Peter     | 2014-03-30 18:54:40 |    0 |    4 |  244 |  14644 |
 | Keith     | 2014-03-30 18:54:11 |    0 |    4 |  244 |  14673 |
 | Andres    | 2014-03-28 09:20:10 |    2 |   61 | 3698 | 221914 |
 | Nadeem    | 2014-03-26 09:33:43 |    4 |  109 | 6565 | 393901 |
 +-----------+---------------------+------+------+------+--------+
 4 rows in set (0.00 sec)
3赞 Choudhury Saadmaan Mahmid 9/30/2014 #26

很简单:

    <?php
        $date1 = date_create("2007-03-24");
        echo "Start date: ".$date1->format("Y-m-d")."<br>";
        $date2 = date_create("2009-06-26");
        echo "End date: ".$date2->format("Y-m-d")."<br>";
        $diff = date_diff($date1,$date2);
        echo "Difference between start date and end date: ".$diff->format("%y years, %m months and %d days")."<br>";
    ?>

详情请查看以下链接:

PHP: date_diff - Manual

请注意,它适用于 PHP 5.3.0 或更高版本。

7赞 CopperRabbit 5/24/2016 #27

您可以随时使用以下函数,该函数可以以年和月为单位返回年龄(即 1 年 4 个月)

function getAge($dob, $age_at_date)
{  
    $d1 = new DateTime($dob);
    $d2 = new DateTime($age_at_date);
    $age = $d2->diff($d1);
    $years = $age->y;
    $months = $age->m;

    return $years.'.'.months;
}

或者,如果您希望在当前日期计算年龄,则可以使用

function getAge($dob)
{  
    $d1 = new DateTime($dob);
    $d2 = new DateTime(date());
    $age = $d2->diff($d1);
    $years = $age->y;
    $months = $age->m;

    return $years.'.'.months;
}

评论

1赞 Maxim Paladi 10/16/2023
谢谢!它看起来很简单。我按如下方式使用它来获得以月为单位的总差异:$months = $age->y * 12 + $age->m;
7赞 bikram kc 6/7/2017 #28

对于 php 版本 >=5.3 :创建两个日期对象,然后使用函数。它将返回 php DateInterval 对象。查看文档date_diff()

$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
2赞 Abhijit 10/4/2017 #29
$date = '2012.11.13';
$dateOfReturn = '2017.10.31';

$substract = str_replace('.', '-', $date);

$substract2 = str_replace('.', '-', $dateOfReturn);



$date1 = $substract;
$date2 = $substract2;

$ts1 = strtotime($date1);
$ts2 = strtotime($date2);

$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);

$month1 = date('m', $ts1);
$month2 = date('m', $ts2);

echo $diff = (($year2 - $year1) * 12) + ($month2 - $month1);
9赞 Adeel 10/16/2017 #30

我更喜欢使用和对象。date_createdate_diff

法典:

$date1 = date_create("2007-03-24");
$date2 = date_create("2009-06-26");

$dateDifference = date_diff($date1, $date2)->format('%y years, %m months and %d days');

echo $dateDifference;

输出:

2 years, 3 months and 2 days

有关更多信息,请阅读 PHP date_diff手册

根据手册是 DateTime::d iff() 的别名date_diff

评论

0赞 Muhammad Mubashirullah Durrani 12/12/2022
我想指出的是,可以date_diff提供一个布尔值 true 来返回绝对差值。你可能会得到一个相反的结果。
11赞 Mosin 12/15/2017 #31

下面是可运行的代码

$date1 = date_create('2007-03-24');
$date2 = date_create('2009-06-26');
$diff1 = date_diff($date1,$date2);
$daysdiff = $diff1->format("%R%a");
$daysdiff = abs($daysdiff);
8赞 larp 12/27/2018 #32

使用 date_diff() 尝试这个非常简单的答案,这是经过测试的。

$date1 = date_create("2017-11-27");
$date2 = date_create("2018-12-29");
$diff=date_diff($date1,$date2);
$months = $diff->format("%m months");
$years = $diff->format("%y years");
$days = $diff->format("%d days");

echo $years .' '.$months.' '.$days;

输出为:

1 years 1 months 2 days
10赞 Waad Mawlood 2/12/2021 #33

使用此功能

//function Diff between Dates
//////////////////////////////////////////////////////////////////////
//PARA: Date Should In YYYY-MM-DD Format
//RESULT FORMAT:
// '%y Year %m Month %d Day %h Hours %i Minute %s Seconds' =>  1 Year 3 Month 14 Day 11 Hours 49 Minute 36 Seconds
// '%y Year %m Month %d Day'                       =>  1 Year 3 Month 14 Days
// '%m Month %d Day'                                     =>  3 Month 14 Day
// '%d Day %h Hours'                                   =>  14 Day 11 Hours
// '%d Day'                                                 =>  14 Days
// '%h Hours %i Minute %s Seconds'         =>  11 Hours 49 Minute 36 Seconds
// '%i Minute %s Seconds'                           =>  49 Minute 36 Seconds
// '%h Hours                                          =>  11 Hours
// '%a Days                                                =>  468 Days
//////////////////////////////////////////////////////////////////////
function dateDifference($date_1 , $date_2 , $differenceFormat = '%a' )
{
    $datetime1 = date_create($date_1);
    $datetime2 = date_create($date_2);

    $interval = date_diff($datetime1, $datetime2);

    return $interval->format($differenceFormat);

}

仅设置参数$differenceFormat根据您的需要 示例:我想要将年份与月和日之间的差异与你的年龄

dateDifference(date('Y-m-d')$date , '%y %m %d')

或其他格式

dateDifference(date('Y-m-d') , $date , '%y-%m-%d')

1赞 mostafa ali 5/6/2022 #34
function showTime($time){

    $start      = strtotime($time);
    $end        = strtotime(date("Y-m-d H:i:s"));
    $minutes    = ($end - $start)/60;


    // years 
    if(($minutes / (60*24*365)) > 1){
        $years = floor($minutes/(60*24*365));
        return "From $years year( s ) ago";
    }


    // monthes 
    if(($minutes / (60*24*30)) > 1){
        $monthes = floor($minutes/(60*24*30));
        return "From $monthes monthe( s ) ago";
    }


    // days 
    if(($minutes / (60*24)) > 1){
        $days = floor($minutes/(60*24));
        return "From $days day( s ) ago";
    }

    // hours 
    if(($minutes / 60) > 1){
        $hours = floor($minutes/60);
        return "From $hours hour( s ) ago";
    }

    // minutes 
    if($minutes > 1){
        $minutes = floor($minutes);
        return "From $minutes minute( s ) ago";
    }
}

echo showTime('2022-05-05 21:33:00');