代码之家  ›  专栏  ›  技术社区  ›  Simon

计算两次约会之间的月数的优雅方法?

  •  56
  • Simon  · 技术社区  · 15 年前

    假设我有两个变量日期,比如

    $date1 = "2009-09-01";
    $date2 = "2010-05-01";
    

    我需要计算一下 $date2 和 $date1 ( $date2 >= $date1 ). 也就是说,我需要 8 .

    有没有办法用 date 函数,或者我必须分解字符串并进行一些计算?

    多谢

    11 回复  |  直到 15 年前
        1
  •  120
  •   Pez Cuckow    13 年前

    对于PHP>=5.3

    $d1 = new DateTime("2009-09-01");
    $d2 = new DateTime("2010-05-01");
    
    var_dump($d1->diff($d2)->m); // int(4)
    var_dump($d1->diff($d2)->m + ($d1->diff($d2)->y*12)); // int(8)
    

    DateTime::diff返回 DateInterval 对象

    如果不使用PHP 5.3或更高版本运行,我想您必须使用unix时间戳:

    $d1 = "2009-09-01";
    $d2 = "2010-05-01";
    
    echo (int)abs((strtotime($d1) - strtotime($d2))/(60*60*24*30)); // 8
    

    但这并不十分精确(并非每个月都有30天)。

    最后一件事:如果这些日期来自您的数据库,那么使用您的DBMS来完成这项工作,而不是PHP。

    编辑: 如果不能使用DateTime::diff或RDBMS,则此代码应该更精确:

    $d1 = strtotime("2009-09-01");
    $d2 = strtotime("2010-05-01");
    $min_date = min($d1, $d2);
    $max_date = max($d1, $d2);
    $i = 0;
    
    while (($min_date = strtotime("+1 MONTH", $min_date)) <= $max_date) {
        $i++;
    }
    echo $i; // 8
    
        2
  •  34
  •   Chuck Burgess    13 年前

    或者,如果需要程序样式:

    $date1 = new DateTime("2009-09-01");
    $date2 = new DateTime("2010-05-01");
    $interval = date_diff($date1, $date2);
    echo $interval->m + ($interval->y * 12) . ' months';
    

    更新 :添加了用于说明年份的代码位。

        3
  •  20
  •   Rob shassss    13 年前

    或者简单的计算可以得出:

    $numberOfMonths = abs((date('Y', $endDate) - date('Y', $startDate))*12 + (date('m', $endDate) - date('m', $startDate)))+1;
    

    准确,在任何情况下都有效。

        4
  •  14
  •   Valentin Despa    12 年前

    在测试了大量的解决方案,将所有内容都放在单元测试中之后,我得出了以下结论:

    /**
     * Calculate the difference in months between two dates (v1 / 18.11.2013)
     *
     * @param \DateTime $date1
     * @param \DateTime $date2
     * @return int
     */
    public static function diffInMonths(\DateTime $date1, \DateTime $date2)
    {
        $diff =  $date1->diff($date2);
    
        $months = $diff->y * 12 + $diff->m + $diff->d / 30;
    
        return (int) round($months);
    }
    

    例如,它将返回(来自单元测试的测试用例):

    • 2013年11月1日-2013年11月30日-1个月
    • 2013年1月1日-2013年12月31日-12个月
    • 2011年1月31日-2011年2月28日-1个月
    • 2009年9月1日-2010年5月1日-8个月
    • 2013年1月1日-2013年3月31日-3个月
    • 2013年2月15日-2013年4月15日-2个月
    • 1985年2月1日-2013年12月31日-347个月

    注意:由于它与天的关系是四舍五入的,所以即使是半个月也会四舍五入,如果在某些情况下使用它可能会导致问题。所以不要在这种情况下使用它,它会引起你的问题。

    例如:

    • 2013年11月2日-2013年12月31日将返回2,而不是1(如预期)。
        5
  •  4
  •   Bekarys Jesus Velazquez    10 年前

    这是获取两个日期之间的月数的另一种方法:

    // Set dates
    $dateIni = '2014-07-01';
    $dateFin = '2016-07-01';
    
    // Get year and month of initial date (From)
    $yearIni = date("Y", strtotime($dateIni));
    $monthIni = date("m", strtotime($dateIni));
    
    // Get year an month of finish date (To)
    $yearFin = date("Y", strtotime($dateFin));
    $monthFin = date("m", strtotime($dateFin));
    
    // Checking if both dates are some year
    
    if ($yearIni == $yearFin) {
       $numberOfMonths = ($monthFin-$monthIni) + 1;
    } else {
       $numberOfMonths = ((($yearFin - $yearIni) * 12) - $monthIni) + 1 + $monthFin;
    }
    
        6
  •  3
  •   manix    11 年前

    我用这个:

    $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);
    
        7
  •  1
  •   pathfinder    13 年前

    使用DateTime,这将为您提供任意月数的更精确的解决方案:

    $d1 = new DateTime("2011-05-14");
    $d2 = new DateTime();
    $d3 = $d1->diff($d2);
    $d4 = ($d3->y*12)+$d3->m;
    echo $d4;
    

    你还需要处理剩下的日子 $d3->d 如果你的现实世界问题并不像最初的问题那么简单,那么两个日期都在月初。

        8
  •  1
  •   pollux1er    12 年前

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

    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;
    }
    
        9
  •  0
  •   ranojan    9 年前

    我用过这个,在任何情况下都能用

    $fiscal_year = mysql_fetch_row(mysql_query("SELECT begin,end,closed FROM fiscal_year WHERE id = '2'"));
    
    
                $date1 = $fiscal_year['begin'];
                $date2 = $fiscal_year['end'];
    
                $ts1 = strtotime($date1);
                $ts2 = strtotime($date2);
    
    
                $te=date('m',$ts2-$ts1);
    
                echo $te;
    
        10
  •  0
  •   Poly    8 年前

    如果日期是mySQL查询结果集的一部分,那么使用TIMESTAMPDIFF函数进行日期计算就容易多了,您可以指定返回单位,例如。 Select TIMESTAMPDIFF(MONTH, start_date, end_date)months_diff from table_name

        11
  •  0
  •   Claudio    7 年前

    SttoTimes不是很精确,它是一个近似计数,它没有考虑到月的实际日期。

    最好把日期安排在每个月都有的日子。

    $date1 = "2009-09-01";
    $date2 = "2010-05-01";
    
    $d1 = mktime(0, 0, 1, date('m', strtotime($date1)), 1, date('Y', strtotime($date1)));
    $d2 = mktime(0, 0, 1, date('m', strtotime($date2)), 1, date('Y', strtotime($date2)));
    
     $total_month = 0;
     while (($d1 = strtotime("+1 MONTH", $d1)) <= $d2) {
         $total_month++;
     }
    echo $total_month;
    
    推荐文章