Façon élégante pour obtenir le nombre de mois entre deux dates?

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

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

J'ai besoin pour obtenir le nombre de mois compris entre $date2 et $date1($date2 >= $date1). C'est-à-dire que je dois obtenir 8.

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

Merci beaucoup

53
demandé sur Simon 2010-11-20 18:59:11

10 réponses

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 renvoie un objetDateInterval

Si vous ne courez pas avec PHP 5.3 ou supérieur, je suppose que vous devrez utiliser des horodatages 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
102
répondu Vincent Savard 2013-08-30 19:48:24

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 tenir compte des années.

26
répondu Chuck Burgess 2013-04-01 02:20:00

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.

17
répondu Mic 2013-06-03 09:35:57

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

/**
 * 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

Avis: En raison de l'arrondi qu'il fait avec les jours, même un demi-mois sera arrondi, ce qui peut conduire à un problème si vous l'utilisez avec certains cas. Donc, ne L'utilisez pas pour 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
répondu Valentin Despa 2013-11-18 11:58:10

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
répondu Jesus Velazquez 2016-08-16 08:07:23

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
répondu manix 2015-01-24 23:18:16

En utilisant DateTime, cela vous donnera une solution plus précise pour n'importe quel nombre de mois:

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

Vous devrez toujours gérer les jours restants $d3->d si votre problème réel n'est pas aussi simple et sec que la question initiale où les deux dates sont le premier du mois.

1
répondu pathfinder 2013-03-30 06:12:27

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
répondu pollux1er 2014-09-05 13:38:27

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
répondu radhason power 2017-10-07 12:17:03

Dans le cas où les dates font partie d'un resultset à partir d'une requête mySQL, il est beaucoup plus facile d'utiliser la fonction TIMESTAMPDIFF pour vos calculs de date et vous pouvez spécifier des unités de retour par exemple. Select TIMESTAMPDIFF(MONTH, start_date, end_date)months_diff from table_name

0
répondu Poly 2018-03-22 07:38:10