2010-11-20 8 views
45

Supongamos que tengo dos fechas en las variables, como¿Una manera elegante de contar el recuento de meses entre dos fechas?

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

que necesito para obtener el recuento de meses entre $date2 y $date1 ($date2 >= $date1). Es decir. Necesito obtener 8.

¿Hay alguna manera de obtenerlo mediante el uso de la función date, o tengo que explotar mis cadenas y hacer algunos cálculos?

Gracias mucho

Respuesta

93

Para 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 devuelve un objeto DateInterval

Si usted no se quede con PHP 5.3 o superior, lo que supongo' tendré que usar marcas de tiempo unix:

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

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

Pero no es muy preciso (no hay siempre 30 días por mes).

Lo último: si esas fechas provienen de su base de datos, entonces use su DBMS para hacer este trabajo, no PHP.

Editar: Este código debe ser más precisa si no se puede utilizar DateTime :: diff o su RDBMS:

$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

¡Gran solución en el bucle while! Muy conciso y preciso. ¡Bien hecho! +1 –

+5

Si tiene dos fechas con más de un año de diferencia, encontrará 'var_dump ($ d1-> diff ($ d2) -> m)' le fallará en el método DateTime (el más alto en esta respuesta) ya que solo mostrará los meses que no suman años. Pruebe esto y vea lo que sucede: '$ d1 = new DateTime (" 2011-05-14 ");' '$ d2 = new DateTime (" 2013-02-02 ");' '$ d3 = $ d1 -> diff ($ d2); ' ' echo '

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

+0

Bueno, no tan rápido ... confiar en strtotime puede darte dolores de cabeza. ¿Cuántos meses hay entre el 31.01.2011 y el 28.02.2011? –

23

O bien, si desea que el estilo de procedimiento:

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

ACTUALIZACIÓN: Se agregó el bit de código a la cuenta de los años.

+1

Si sus fechas están a más de un año de distancia, esto no funcionará. Debería agregar los años * 12 a su respuesta para obtener los meses. – pathfinder

+1

Correcto eres. Actualizado para tener en cuenta los posibles períodos de año. –

1

Usando DateTime, esto le dará una solución más precisa para cualquier cantidad de meses:

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

Usted todavía necesita para manejar los días sobrantes $d3->d si su problema del mundo real no es tan simple y cortar y seco como la pregunta original donde ambas fechas son el primer día del mes.

13

O un simple cálculo daría:

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

preciso y funciona en todos los casos.

+0

Esto es genial, excepto que siempre está desactivado por 1. ¡Elimine el "+1" al final! : D – supercoolville

11

Después de probar un montón de soluciones, poniendo todo en una prueba de unidad, esto es lo que yo salga con:

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

Por ejemplo, se volverá (casos de prueba de la prueba de la unidad):

  • 01.11.2013 - 30.11.2013 - 1 mes
  • 01.01.2013 - 31.12.2013 - 12 meses
  • 31.01.2011 - 28.02.2011 - 1 mes
  • 01/09/2009 a 01/05/2010 - 8 meses
  • 01.01.2013 - 31.03.2013 - 3 meses
  • 02/15/2013 - 04/15/2013 - 2 meses
  • 02/01/1985 - 31.12.2013 - 347 meses

Aviso: Debido al redondeo con los días, incluso se redondeará medio mes, lo que puede ocasionar problemas si lo usa en algunos casos. Así que NO lo use para tales casos, le causará problemas.

Por ejemplo:

  • 02.11.2013 - 31.12.2013 volverá 2, no 1 (como se esperaba).
+1

Esta solución es válida para una cantidad de meses "legible por humanos" entre: Devuelve lo que un humano esperaría ver. En este caso, el redondeo mencionado anteriormente es realmente útil, y obtienes 'problemas' con los usuarios si no lo haces. – Steve

+0

31.01.2011 - 01.03.2011 - 1 mes ==> debe ser de 2 meses – manish1706

1

Este es un método simple que escribí en mi clase para contar el número de meses que participan en dos fechas dadas:

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

Si bien le doy un +1 ya que este es el más cercano para dar resultados reales. Todavía no está completo, ya que fallará para las fechas en el mismo mes. –

3

utilizo este:

$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

Ésta es otra manera para obtener el número de meses entre dos fechas:

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

Esta debería ser la respuesta correcta :) –

0

Lo he usado y funciona en todas las condiciones

$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; 
Cuestiones relacionadas