优雅的方式来获得两个日期之间的月数?

时间:2022-08-03 21:31:11

Let's assume i have two dates in variables, like

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

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

I need to get the count of months between $date2 and $date1($date2 >= $date1). I.e. i need to get 8.

我需要得到$ date2和$ date1之间的月数($ date2> = $ date1)。即我需要8。

Is there a way to get it by using date function, or i have to explode my strings and do some calculations?

有没有办法通过使用日期函数来获取它,或者我必须爆炸我的字符串并进行一些计算?

Thanks much

非常感谢

10 个解决方案

#1


96  

For PHP >= 5.3

对于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 returns a DateInterval object

DateTime :: diff返回DateInterval对象

If you don't run with PHP 5.3 or higher, I guess you'll have to use unix timestamps :

如果你不使用PHP 5.3或更高版本运行,我想你将不得不使用unix时间戳:

$d1 = "2009-09-01";
$d2 = "2010-05-01";

echo (int)abs((strtotime($d1) - strtotime($d2))/(60*60*24*30)); // 8

But it's not very precise (there isn't always 30 days per month).

但它不是很精确(每月不总是30天)。

Last thing : if those dates come from your database, then use your DBMS to do this job, not PHP.

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

Edit: This code should be more precise if you can't use DateTime::diff or your RDBMS :

编辑:如果你不能使用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


24  

Or, if you want the procedural style:

或者,如果您想要程序样式:

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

UPDATE: Added the bit of code to account for the years.

更新:添加了一些代码来解释这些年。

#3


15  

Or a simple calculation would give :

或者简单的计算会给出:

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

Accurate and works in all cases.

准确,适用于所有情况。

#4


12  

After testing tons of solutions, putting all in a unit test, this is what I come out with:

在测试了大量的解决方案后,将所有解决方案全部置于单元测试中,这就是我提出的问题:

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

For example it will return (test cases from the unit test):

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

  • 01.11.2013 - 30.11.2013 - 1 month
  • 01.11.2013 - 30.11.2013 - 1个月
  • 01.01.2013 - 31.12.2013 - 12 months
  • 01.01.2013 - 2013年12月31日 - 12个月
  • 31.01.2011 - 28.02.2011 - 1 month
  • 2011年1月31日 - 2011年2月28日 - 1个月
  • 01.09.2009 - 01.05.2010 - 8 months
  • 01.09.2009 - 01.05.2010 - 8个月
  • 01.01.2013 - 31.03.2013 - 3 months
  • 01.01.2013 - 2013年3月31日 - 3个月
  • 15.02.2013 - 15.04.2013 - 2 months
  • 15.02.2013 - 2013年4月15日 - 2个月
  • 01.02.1985 - 31.12.2013 - 347 months
  • 01.02.1985 - 2013年12月31日 - 347个月

Notice: Because of the rounding it does with the days, even a half of a month will be rounded, which may lead to issue if you use it with some cases. So DO NOT USE it for such cases, it will cause you issues.

注意:由于它与日期的舍入,甚至半个月都会四舍五入,如果你在某些情况下使用它可能会导致问题。所以不要在这种情况下使用它,它会引起你的问题。

For example:

例如:

  • 02.11.2013 - 31.12.2013 will return 2, not 1 (as expected).
  • 02.11.2013 - 2013年12月31日将返回2,而不是1(如预期的那样)。

#5


3  

I use this:

我用这个:

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

#6


3  

This is another way to get the number of months between two dates:

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

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

#7


1  

Using DateTime, this will give you a more accurate solution for any amount of months:

使用DateTime,这将为您提供更准确的解决方案,适用于任何月份:

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

You would still need to handle the leftover days $d3->d if your real world problem is not as simple and cut and dry as the original question where both dates are on the first of the month.

你仍然需要处理剩余的日子$ d3-> d,如果你的真实世界问题不像原始问题那样简单和干燥,两个日期都在这个月的第一天。

#8


1  

This is a simple method I wrote in my class to count the number of months involved into two given dates :

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

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  

I have used this and works in all conditions

我已经使用过这个并且适用于所有条件

$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  

In case the dates are part of a resultset from a mySQL query, it is much easier to use the TIMESTAMPDIFF function for your date calculations and you can specify return units eg. Select TIMESTAMPDIFF(MONTH, start_date, end_date)months_diff from table_name

如果日期是mySQL查询的结果集的一部分,则使用TIMESTAMPDIFF函数更容易进行日期计算,并且可以指定返回单位,例如。从table_name中选择TIMESTAMPDIFF(MONTH,start_date,end_date)months_diff

#1


96  

For PHP >= 5.3

对于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 returns a DateInterval object

DateTime :: diff返回DateInterval对象

If you don't run with PHP 5.3 or higher, I guess you'll have to use unix timestamps :

如果你不使用PHP 5.3或更高版本运行,我想你将不得不使用unix时间戳:

$d1 = "2009-09-01";
$d2 = "2010-05-01";

echo (int)abs((strtotime($d1) - strtotime($d2))/(60*60*24*30)); // 8

But it's not very precise (there isn't always 30 days per month).

但它不是很精确(每月不总是30天)。

Last thing : if those dates come from your database, then use your DBMS to do this job, not PHP.

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

Edit: This code should be more precise if you can't use DateTime::diff or your RDBMS :

编辑:如果你不能使用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


24  

Or, if you want the procedural style:

或者,如果您想要程序样式:

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

UPDATE: Added the bit of code to account for the years.

更新:添加了一些代码来解释这些年。

#3


15  

Or a simple calculation would give :

或者简单的计算会给出:

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

Accurate and works in all cases.

准确,适用于所有情况。

#4


12  

After testing tons of solutions, putting all in a unit test, this is what I come out with:

在测试了大量的解决方案后,将所有解决方案全部置于单元测试中,这就是我提出的问题:

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

For example it will return (test cases from the unit test):

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

  • 01.11.2013 - 30.11.2013 - 1 month
  • 01.11.2013 - 30.11.2013 - 1个月
  • 01.01.2013 - 31.12.2013 - 12 months
  • 01.01.2013 - 2013年12月31日 - 12个月
  • 31.01.2011 - 28.02.2011 - 1 month
  • 2011年1月31日 - 2011年2月28日 - 1个月
  • 01.09.2009 - 01.05.2010 - 8 months
  • 01.09.2009 - 01.05.2010 - 8个月
  • 01.01.2013 - 31.03.2013 - 3 months
  • 01.01.2013 - 2013年3月31日 - 3个月
  • 15.02.2013 - 15.04.2013 - 2 months
  • 15.02.2013 - 2013年4月15日 - 2个月
  • 01.02.1985 - 31.12.2013 - 347 months
  • 01.02.1985 - 2013年12月31日 - 347个月

Notice: Because of the rounding it does with the days, even a half of a month will be rounded, which may lead to issue if you use it with some cases. So DO NOT USE it for such cases, it will cause you issues.

注意:由于它与日期的舍入,甚至半个月都会四舍五入,如果你在某些情况下使用它可能会导致问题。所以不要在这种情况下使用它,它会引起你的问题。

For example:

例如:

  • 02.11.2013 - 31.12.2013 will return 2, not 1 (as expected).
  • 02.11.2013 - 2013年12月31日将返回2,而不是1(如预期的那样)。

#5


3  

I use this:

我用这个:

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

#6


3  

This is another way to get the number of months between two dates:

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

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

#7


1  

Using DateTime, this will give you a more accurate solution for any amount of months:

使用DateTime,这将为您提供更准确的解决方案,适用于任何月份:

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

You would still need to handle the leftover days $d3->d if your real world problem is not as simple and cut and dry as the original question where both dates are on the first of the month.

你仍然需要处理剩余的日子$ d3-> d,如果你的真实世界问题不像原始问题那样简单和干燥,两个日期都在这个月的第一天。

#8


1  

This is a simple method I wrote in my class to count the number of months involved into two given dates :

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

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  

I have used this and works in all conditions

我已经使用过这个并且适用于所有条件

$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  

In case the dates are part of a resultset from a mySQL query, it is much easier to use the TIMESTAMPDIFF function for your date calculations and you can specify return units eg. Select TIMESTAMPDIFF(MONTH, start_date, end_date)months_diff from table_name

如果日期是mySQL查询的结果集的一部分,则使用TIMESTAMPDIFF函数更容易进行日期计算,并且可以指定返回单位,例如。从table_name中选择TIMESTAMPDIFF(MONTH,start_date,end_date)months_diff