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
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
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.
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.
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).
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;
}
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);
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.
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;
}
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;
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