2010-11-20 11 views
45

Supposons que j'ai deux dates dans les variables, commeUne façon élégante d'obtenir le nombre de mois entre deux dates?

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

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

Y at-il un moyen de l'obtenir en utilisant date fonction, ou je dois exploser mes chaînes et faire quelques calculs?

Merci beaucoup

Répondre

93

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 objet DateInterval

Si vous ne vous précipitiez pas avec PHP 5.3 ou plus, je suppose que vous » Il faudra utiliser un horodatage 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 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 
+0

Grande solution sur la boucle while! Très concis et précis. Bien joué! +1 –

+5

Si vous avez deux dates distantes de plus d'un an, vous verrez 'var_dump ($ d1-> diff ($ d2) -> m)' échouera dans la méthode DateTime (la plus haute sur cette réponse) car elle ne montrera que les mois qui ne correspondent pas aux années. Essayez ceci et voyez ce qui se passe: '$ d1 = nouveau DateTime (" 2011-05-14 ");' '$ d2 = nouveau DateTime (" 2013-02-02 ");' '$ d3 = $ d1 -> diff ($ d2); 'echo '

'.print_r($d3,true).'
';' – pathfinder

+0

Eh bien pas si vite ... compter sur strtotime peut vous donner des maux de tête. Combien de mois se situent entre le 31.01.2011 et le 28.02.2011? –

23

Ou, si vous voulez le style de procédure:

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

MISE À JOUR: Ajout du bit de code pour tenir compte des années.

+1

Si vos dates sont à plus d'un an d'intervalle, cela échouera. Vous auriez besoin d'ajouter les années * 12 à votre réponse pour obtenir les mois. – pathfinder

+1

Correct vous êtes. Mise à jour pour tenir compte des périodes d'année possibles. –

1

En utilisant DateTime, cela vous donnera une solution plus précise pour un montant de mois:

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

Vous auriez encore besoin de gérer les jours restants $d3->d si votre problème du monde réel n'est pas aussi simple et couper et sécher comme la question originale où les deux dates sont le premier du mois.

13

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.

+0

C'est super, sauf qu'il est toujours désactivé de 1. Supprimer le "+1" à la fin! : D – supercoolville

11

Après avoir testé des tonnes de solutions, mettre tous dans un test unitaire, ce que je viens 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 sera de retour (cas de test à partir du test unitaire):

  • 11.01.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
  • 02/01/1985 - 31.12.2013 - 347 mois

Remarque: En raison de l'arrondi, il fait avec les jours, même une demi-mois sera arrondi, ce qui peut entraîner des problèmes si vous l'utilisez dans 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).
+1

Cette solution est bonne pour un nombre de mois "lisible par l'homme" entre: Il renvoie ce que l'homme s'attendrait à voir. Dans ce cas, l'arrondi mentionné ci-dessus est réellement utile, et vous obtenez des «problèmes» avec les utilisateurs si vous ne le faites pas! – Steve

+0

31.01.2011 - 01.03.2011 - 1 mois ==> devrait être 2 mois – manish1706

1

Ceci est une méthode simple je l'ai écrit dans ma classe pour compter le nombre de mois concerné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; 
} 
+0

Alors que je lui donne un +1 puisque c'est le plus proche de donner des résultats concrets. Cependant, il n'est pas complet, car il échouera pour les dates du même mois. –

3

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

C'est une autre façon pour 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; 
} 
+0

Cela devrait être la bonne annéewear :) –

0

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;