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