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

如何使用PHP计算两个日期之间的差异?,php,datetime,datediff,Php,Datetime,Datediff,我有两个表格日期: Start Date: 2007-03-24 End Date: 2009-06-26 现在我需要通过以下形式找出这两者之间的区别: 2 years, 3 months and 2 days 如何在PHP中实现这一点 将其用于遗留代码(PHP

我有两个表格日期:

Start Date: 2007-03-24 
End Date: 2009-06-26
现在我需要通过以下形式找出这两者之间的区别:

2 years, 3 months and 2 days
如何在PHP中实现这一点

将其用于遗留代码(PHP<5.3)。有关最新的解决方案,请参见以下jurka的答案

您可以使用strotime()将两个日期转换为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所述。我的代码通常仅在您没有PHP5.3或更高版本时推荐

评论中的一些人指出,上面的代码只是一个近似值。我仍然相信,对于大多数情况来说,这是可以的,因为范围的使用更多的是提供一种时间已经过去或仍然存在的感觉,而不是提供精度——如果您想这样做,只需输出日期

尽管如此,我还是决定处理投诉。如果您确实需要一个精确的范围,但还没有访问PHP5.3,请使用下面的代码(它也应该在PHP4中工作)。这是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)));
您可以使用

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

在上述代码之前

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

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


请参阅。

查看小时、分钟和秒

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

我不知道你是否在使用PHP框架,但是很多PHP框架都有日期/时间库和帮助器来帮助你避免重蹈覆辙

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

1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes
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

我建议使用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 ";
阅读更多

从手册中:

从PHP5.2.2开始,可以使用比较运算符比较DateTime对象

$date1=新的日期时间(“现在”);
$date2=新的日期时间(“明天”);
变量转储($date1==$date2);//布尔(假)
变量转储($date1<$date2);//布尔(真)
变量转储($date1>$date2);//布尔(假)
我投了赞成票,因为那是我最喜欢的,但我有一个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;
}
结果是:

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
参数,或者在输出字符串时过滤掉它们,您可以非常轻松地删除不需要的间隔(比如“周”)。

当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);
        }
函数日期差($startDate,$endDate)
{
$startDate=strottime($startDate);
$endDate=strottime($endDate);
如果($startDate==false | |$startDate<0 | |$endDate==false | |$endDate<0 | |$startDate>$endDate)
返回false;
$years=日期($Y',$endDate)-日期($Y',$startDate);
$endMonth=日期('m',$endDate);
$startMonth=日期($m',$startDate);
//计算月份
$months=$endMonth-$startMonth;
如果($months
看看下面的链接。这是迄今为止我找到的最好答案:)

当你通过考试时,哪一天是早一点还是晚一点都不重要 日期参数。该函数使用PHP ABS()绝对值 始终返回一个正数作为两者之间的天数 日期

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

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


我有一些简单的逻辑:

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

不久前,我编写了一个
格式化日期
函数,因为它为如何选择约会提供了很多选项:

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

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

  • 仅适用于PHP5.3+(但这不再是一个好借口)
  • 仅支持年、月、日、小时、分钟和秒(无周)
  • 它计算上述所有+天的差异(您不能仅在几个月内获得差异)
  • 为了克服这个问题,我编写了以下代码(改进自):

    它运行两个循环;第一个循环通过暴力强制处理相对间隔(年和月),第二个循环通过简单的算法计算额外的绝对间隔(因此速度更快):

    最佳课程
    <?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);
    ?>
    
    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
        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;
          ?>
    
    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);
    }    
    
    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);
    }
    
    $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);
    
    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
    
    /**
     * 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;
    }
    
    echo format_interval($difference);
    
    /**
     * 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);
    
    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);
    }
    
    $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 ";
    
    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;
        }
    }
    
    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';
    }
    
    <?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);
    
    $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;
    
    /**
     * 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';
    }
    
    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)
    
        <?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>";
        ?>
    
    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;
    }
    
    $date1=date_create("2007-03-24");
    $date2=date_create("2009-06-26");
    $diff=date_diff($date1,$date2);
    echo $diff->format("%R%a days");
    
    $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
    
    $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);
    
    $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