40

如果不使用 PHP 5.3 的date_diff函数(我使用的是 PHP 5.2.17),是否有一种简单而准确的方法来做到这一点?我正在考虑类似下面的代码,但我不知道如何计算闰年:

$days = ceil(abs( strtotime('2000-01-25') - strtotime('2010-02-20') ) / 86400);
$months = ???;

我正在尝试计算一个人的月龄。

4

15 回答 15

107
$date1 = '2000-01-25';
$date2 = '2010-02-20';

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

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

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

$diff = (($year2 - $year1) * 12) + ($month2 - $month1);

您可能还想在某处包含日期,具体取决于您是否指月。希望你明白这一点。

于 2012-11-16T12:52:17.957 回答
21

这是我在课堂上编写的一种简单方法,用于计算两个给定日期所涉及的月数:

public function nb_mois($date1, $date2)
{
    $begin = new DateTime( $date1 );
    $end = new DateTime( $date2 );
    $end = $end->modify( '+1 month' );

    $interval = DateInterval::createFromDateString('1 month');

    $period = new DatePeriod($begin, $interval, $end);
    $counter = 0;
    foreach($period as $dt) {
        $counter++;
    }

    return $counter;
}
于 2014-09-05T11:24:52.523 回答
18

这是我的解决方案。它检查日期的年份和月份并找出差异。

 $date1 = '2000-01-25';
 $date2 = '2010-02-20';
 $d1=new DateTime($date2); 
 $d2=new DateTime($date1);                                  
 $Months = $d2->diff($d1); 
 $howeverManyMonths = (($Months->y) * 12) + ($Months->m);
于 2019-04-09T12:48:33.017 回答
3

像这样:

$date1 = strtotime('2000-01-25');
$date2 = strtotime('2010-02-20');
$months = 0;

while (($date1 = strtotime('+1 MONTH', $date1)) <= $date2)
    $months++;

echo $months;

如果要包括天数,请使用以下命令:

$date1 = strtotime('2000-01-25');
$date2 = strtotime('2010-02-20');

$months = 0;

while (strtotime('+1 MONTH', $date1) < $date2) {
    $months++;
    $date1 = strtotime('+1 MONTH', $date1);
}

echo $months, ' month, ', ($date2 - $date1) / (60*60*24), ' days'; // 120 month, 26 days
于 2012-11-16T12:52:10.437 回答
2

这就是我最终解决它的方式。我知道我有点晚了,但我希望这可以节省很多时间和代码行。
我使用 DateInterval::format 以年、月和日的形式显示人类可读的倒计时时钟。检查https://www.php.net/manual/en/dateinterval.format.php以获取格式表,以查看有关如何修改返回值的选项。应该给你你正在寻找的东西。

$origin = new DateTime('2020-10-01');
$target = new DateTime('2020-12-25');
$interval = $origin->diff($target);
echo $interval->format('%y years, %m month, %d days until Christmas.');

输出:0 年,2 个月,24 天

于 2020-10-01T17:57:21.837 回答
2

这是我的解决方案。它只检查日期的年份和月份。因此,如果一个日期是31.10.15,另一个是02.11.15返回 1 个月。

function get_interval_in_month($from, $to) {
    $month_in_year = 12;
    $date_from = getdate(strtotime($from));
    $date_to = getdate(strtotime($to));
    return ($date_to['year'] - $date_from['year']) * $month_in_year -
        ($month_in_year - $date_to['mon']) +
        ($month_in_year - $date_from['mon']);
}
于 2015-12-29T13:36:29.520 回答
1

我最近需要计算从产前到 5 岁(60 个月以上)的月龄。

上面的答案都不适合我。我尝试的第一个,这基本上是 deceze 答案的 1 班轮

$bdate = strtotime('2011-11-04'); 
$edate = strtotime('2011-12-03');
$age = ((date('Y',$edate) - date('Y',$bdate)) * 12) + (date('m',$edate) - date('m',$bdate));
. . .

这在设定的日期失败,显然答案应该是 0,因为尚未达到月标记(2011-12-04),但代码返回 1。

我尝试的第二种方法,使用亚当的代码

$bdate = strtotime('2011-01-03'); 
$edate = strtotime('2011-02-03');
$age = 0;

while (strtotime('+1 MONTH', $bdate) < $edate) {
    $age++;
    $bdate = strtotime('+1 MONTH', $bdate);
}
. . .

这失败并说 0 个月,当它应该是 1 时。

对我有用的是对这段代码的一点扩展。我使用的是以下内容:

$bdate = strtotime('2011-11-04');
$edate = strtotime('2012-01-04');
$age = 0;

if($edate < $bdate) {
    //prenatal
    $age = -1;
} else {
    //born, count months.
    while($bdate < $edate) {
        $age++;
        $bdate = strtotime('+1 MONTH', $bdate);
        if ($bdate > $edate) {
            $age--;
        }
    }
}
于 2013-10-31T18:02:19.987 回答
1

我解决问题的功能

function diffMonth($from, $to) {

        $fromYear = date("Y", strtotime($from));
        $fromMonth = date("m", strtotime($from));
        $toYear = date("Y", strtotime($to));
        $toMonth = date("m", strtotime($to));
        if ($fromYear == $toYear) {
            return ($toMonth-$fromMonth)+1;
        } else {
            return (12-$fromMonth)+1+$toMonth;
        }

    }
于 2015-10-09T04:18:55.043 回答
1

我的解决方案是几个答案的混合。我不想做一个循环,特别是当我在 $interval->diff 中有所有数据时,我只是做了数学计算,如果就我而言,月数可能是负数,所以这是我的方法。

    /**
     * Function will give you the difference months between two dates
     *
     * @param string $start_date
     * @param string $end_date
     * @return int|null
     */
    public function get_months_between_dates(string $start_date, string $end_date): ?int
    {
        $startDate = $start_date instanceof Datetime ? $start_date : new DateTime($start_date);
        $endDate = $end_date instanceof Datetime ? $end_date : new DateTime($end_date);
        $interval = $startDate->diff($endDate);
        $months = ($interval->y * 12) + $interval->m;
        
       return $startDate > $endDate ? -$months : $months;
        
    }
于 2021-01-22T17:04:35.957 回答
0

这个怎么样:

$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-09-01");
$months = 0;

$d1->add(new \DateInterval('P1M'));
while ($d1 <= $d2){
    $months ++;
    $d1->add(new \DateInterval('P1M'));
}

print_r($months);
于 2015-01-24T23:04:39.480 回答
0

跟进@deceze 的回答(我对他的回答投了赞成票)。即使第一个日期的日期没有到达第二个日期的日期,月份仍将作为一个整体计算。

这是我关于包括这一天的简单解决方案:

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

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

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

$day1 = date('d', $ts1); /* I'VE ADDED THE DAY VARIABLE OF DATE1 AND DATE2 */
$day2 = date('d', $ts2);

$diff = (($year2 - $year1) * 12) + ($month2 - $month1);

/* IF THE DAY2 IS LESS THAN DAY1, IT WILL LESSEN THE $diff VALUE BY ONE */

if($day2<$day1){ $diff=$diff-1; }

逻辑是,如果第二个日期的日期小于第一个日期的日期,它会将$diff变量的值减一。

于 2014-11-20T06:14:57.673 回答
0
$date1 = '2000-01-25';
$date2 = '2010-02-20';

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

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

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

$diff = (($year2 - $year1) * 12) + ($month2 - $month1);

如果月份从一月切换到二月,上面的代码将为您返回 $diff = 1 但如果您只想在 30 天后考虑下个月,则添加下面的代码行以及上面的代码行。

$day1 = date('d', $ts1);
$day2 = date('d', $ts2);

if($day2 < $day1){ $diff = $diff - 1; }
于 2019-02-27T04:48:17.567 回答
0

要计算两个日期之间的日历月数(也如此问,我通常最终会做这样的事情。我将这两个日期转换为“2020-05”和“1994-05”之类的字符串,然后从下面的函数中获取它们各自的结果,然后对这些结果进行减法运算。

/**
 * Will return number of months. For 2020 April, that will be the result of (2020*12+4) = 24244
 * 2020-12 = 24240 + 12 = 24252
 * 2021-01 = 24252 + 01 = 24253
 * @param string $year_month Should be "year-month", like "2020-04" etc.
 */
static private function calculate_month_total($year_month)
{
    $parts = explode('-', $year_month);
    $year = (int)$parts[0];
    $month = (int)$parts[1];
    return $year * 12 + $month;
}
于 2020-07-03T15:46:26.627 回答
0
function date_duration($date){
    $date1 = new DateTime($date);
    $date2 = new DateTime();
    $interval = $date1->diff($date2);
    if($interval->y > 0 and $interval->y < 2){
        return $interval->y.' year ago';
    }else if($interval->y > 1){
        return $interval->y.' years ago';
    }else if($interval->m > 0 and $interval->m < 2){
        return $interval->m.' month ago';
    }else if($interval->m > 1){
        return $interval->y.' months ago';
    }else if($interval->d > 1){
        return $interval->d.' days ago';
    }else{
        if($interval->h > 0 and $interval->h < 2){
            return $interval->h.' hour ago';
        }else if($interval->h > 1){
            return $interval->h.' hours ago';
        }else{
            if($interval->i > 0 and $interval->i < 2){
                return $interval->i.' minute ago';
            }else if($interval->i > 1){
                return $interval->i.' minutes ago';
            }else{
                return 'Just now';
            }
        }
    }
}

返回 11 个月前、2 年前、5 分钟前的日期区分样式

例子:

echo date_duration('2021-02-28 14:59:00.00');

将根据您当前的月份返回“1 个月前”

于 2021-03-31T14:09:16.453 回答
0

我只是想分享我写的函数。您可以通过输入相关的日期时间格式来修改它以获得月份和年份,以定义修饰符 aka modify("+1 something")。

/**
 * @param DateTimeInterface $start a anything using the DateTime interface
 * @param DateTimeInterface|null $end to calculate the difference to
 * @param string $modifier for example: day or month or year.
 * @return int the count of periods.
 */
public static function elapsedPeriods(
                       DateTimeInterface $start, 
                       DateTimeInterface $end = null, 
                       string            $modifier = '1 month'
): int
{

    // just an addition, in case you just want the periods up untill now
    if ($end === null ) {
        $end = new DateTime();
    }

    // we clone the start, because we dont want to change the actual start
    // (objects are passed by ref by default, so if you forget this you might 
    // mess up your data)
    $cloned_start = clone $start;

    // we create a period counter, starting at zero, because we want to count 
    // periods, assuming the first try, makes one period. 
    // (week, month, year, et cetera) 
    $period_count = 0;
    
    // so while our $cloned_start is smaller to the $end (or now).
    // we will increment the counter
    while ($cloned_start < $end) {
        // first off we increment the count, for the first iteration could end 
        // the cycle
        $period_count++;
        // now we modify the cloned start
        $cloned_start->modify(sprintf("+1 %s", $modifier));
    }

    return $period_count; // return the count
}

干杯

于 2021-08-29T20:44:21.503 回答