web-dev-qa-db-fra.com

Manière élégante de compter le nombre de mois entre deux dates?

Supposons que j'ai deux dates dans des variables, comme 

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

Je dois connaître le nombre de mois entre $date2 et $date1 ($date2 >= $date1). C'est à dire. J'ai besoin d'obtenir 8.

Existe-t-il un moyen de l'obtenir en utilisant date function, ou je dois exploser mes chaînes et faire des calculs?

Merci beaucoup

55
Simon

Pour 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 retourne un DateInterval object

Si vous ne courez pas avec PHP 5.3 ou supérieur, vous devrez utiliser des timestamps unix

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

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

Mais ce n'est pas très précis (il n'y a pas toujours 30 jours par mois).

Dernière chose: si ces dates proviennent de votre base de données, utilisez votre SGBD pour faire ce travail, pas PHP.

Edit: Ce code devrait être plus précis si vous ne pouvez pas utiliser DateTime :: diff ou votre SGBDR:

$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
109
Vincent Savard

Ou, si vous voulez le style procédural:

$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: Ajout du bit de code pour rendre compte des années.

26
Chuck Burgess

Ou un simple calcul donnerait:

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

Précis et fonctionne dans tous les cas.

18
Mic

Après avoir testé des tonnes de solutions, en mettant le tout dans un test unitaire, voici ce que je propose:

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

Par exemple, il retournera (cas de test du test unitaire):

  • 01.11.2013 - 30.11.2013 - 1 mois
  • 01.01.2013 - 31.12.2013 - 12 mois
  • 31.01.2011 - 28.02.2011 - 1 mois
  • 01.09.2009 - 01.05.2010 - 8 mois
  • 01.01.2013 - 31.03.2013 - 3 mois
  • 15.02.2013 - 15.04.2013 - 2 mois
  • 01.02.1985 - 31.12.2013 - 347 mois

Remarque: en raison de l'arrondissement des jours, même un demi-mois sera arrondi, ce qui peut entraîner des problèmes si vous l'utilisez dans certains cas. Donc, ne l'utilisez pas dans de tels cas, cela vous causera des problèmes.

Par exemple:

  • 02.11.2013 - 31.12.2013 retournera 2, pas 1 (comme prévu). 
13
Valentin Despa

C'est une autre façon d'obtenir le nombre de mois entre deux 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;
}
4
Jesus Velazquez

J'utilise ceci:

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

En utilisant DateTime, cela vous donnera une solution plus précise pour tous les mois:

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

Vous aurez toujours besoin de gérer les jours restants $d3->d si votre problème du monde réel n’est pas aussi simple et aussi simple que la question initiale, où les deux dates figurent le premier du mois.

1
pathfinder

C'est une méthode simple que j'ai écrite dans ma classe pour compter le nombre de mois impliqués en deux dates données:

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;
}
1
pollux1er

Je l'ai utilisé et fonctionne dans toutes les 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;
0
radhason power

strtotime n'est pas très précis, il effectue un décompte approximatif, il ne tient pas compte des jours réels du mois.

il est préférable d’apporter les dates à un jour qui est toujours présent chaque mois.

$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;
0
Claudio