2010-04-21 19 views
10

¿Hay alguna manera de encontrar la diferencia mensual en PHP? Tengo el aporte de desde la fecha 2003-10-17 hasta la fecha 2004-03-24. Necesito encontrar cuántos meses hay dentro de estos dos días. Digamos que si son 6 meses, necesito la salida solo en meses. Gracias por guiarme por la diferencia del día.Find Month difference in php?

Encuentro la solución a través de MySQL pero la necesito en PHP. Alguien me ayude, Gracias de antemano.

+2

¿Qué es exactamente un mes en este caso? El mes calendario? ¿30 dias? –

+3

Duplicados: http://stackoverflow.com/search?q=date+difference+php – Gordon

Respuesta

-2

Aquí hay una rápida uno:

$date1 = mktime(0,0,0,10,0,2003); // m d y, use 0 for day 
$date2 = mktime(0,0,0,3,0,2004); // m d y, use 0 for day 

echo round(($date2-$date1)/60/60/24/30); 
+21

Esto se volverá cada vez más impreciso cuanto más alejadas estén las dos fechas y, con el tiempo, podrían terminar en la dirección equivocada ... – deceze

+7

¿Qué pasará si el mes tiene '31 días' en el caso' enero, marzo, mayo, julio, agosto, octubre, diciembre' o '28 días' en el caso' febrero', porque está dividido por 30. – Frank

0
<?php 
    # end date is 2008 Oct. 11 00:00:00 
    $_endDate = mktime(0,0,0,11,10,2008); 
    # begin date is 2007 May 31 13:26:26 
    $_beginDate = mktime(13,26,26,05,31,2007); 

    $timestamp_diff= $_endDate-$_beginDate +1 ; 
    # how many days between those two date 
    $days_diff = $timestamp_diff/2635200; 

?> 

Referencia: http://au.php.net/manual/en/function.mktime.php#86916

+4

Mismo problema que la solución de @ Kai, muy optimista Asumiendo que un mes tiene 30 días ... – deceze

60

La manera más fácil sin reinventar la rueda. Esto le dará la diferencia completa meses. Es decir. las dos fechas siguientes son casi separadas 76 meses, pero el resultado es 75 meses.

date_default_timezone_set('Asia/Tokyo'); // you are required to set a timezone 

$date1 = new DateTime('2009-08-12'); 
$date2 = new DateTime('2003-04-14'); 

$diff = $date1->diff($date2); 

echo (($diff->format('%y') * 12) + $diff->format('%m')) . " full months difference"; 
+0

buen trabajo: solo una pequeña pregunta en esto ¿cómo obtener el número de días usando esto? –

+2

@noobie Por favor [RTFM para 'DateInterval :: format'] (http://php.net/manual/en/dateinterval.format.php) para encontrar todas las opciones de formato posibles. – deceze

+1

Resultados extraños: Desde: 2013-03-01, Hasta: 2013-04-01, año diff: 0, mes diff: 1, días diff: 3. Meses con menos de 31 días también dan diff en meses = 0 – thehpi

0
function monthsDif($start, $end) 
{ 
    // Assume YYYY-mm-dd - as is common MYSQL format 
    $splitStart = explode('-', $start); 
    $splitEnd = explode('-', $end); 

    if (is_array($splitStart) && is_array($splitEnd)) { 
     $startYear = $splitStart[0]; 
     $startMonth = $splitStart[1]; 
     $endYear = $splitEnd[0]; 
     $endMonth = $splitEnd[1]; 

     $difYears = $endYear - $startYear; 
     $difMonth = $endMonth - $startMonth; 

     if (0 == $difYears && 0 == $difMonth) { // month and year are same 
      return 0; 
     } 
     else if (0 == $difYears && $difMonth > 0) { // same year, dif months 
      return $difMonth; 
     } 
     else if (1 == $difYears) { 
      $startToEnd = 13 - $startMonth; // months remaining in start year(13 to include final month 
      return ($startToEnd + $endMonth); // above + end month date 
     } 
     else if ($difYears > 1) { 
      $startToEnd = 13 - $startMonth; // months remaining in start year 
      $yearsRemaing = $difYears - 2; // minus the years of the start and the end year 
      $remainingMonths = 12 * $yearsRemaing; // tally up remaining months 
      $totalMonths = $startToEnd + $remainingMonths + $endMonth; // Monthsleft + full years in between + months of last year 
      return $totalMonths; 
     } 
    } 
    else { 
     return false; 
    } 
} 
+1

Ammended - changed $ startToEnd = 12 - $ startMonth; to $ startToEnd = 13 - $ startMonth; Como antes no contaba la duración de diciembre –

6

Wow, manera de pensar demasiado en el problema ... ¿Qué hay de esta versión:

function monthsBetween($startDate, $endDate) { 
    $retval = ""; 

    // Assume YYYY-mm-dd - as is common MYSQL format 
    $splitStart = explode('-', $startDate); 
    $splitEnd = explode('-', $endDate); 

    if (is_array($splitStart) && is_array($splitEnd)) { 
     $difYears = $splitEnd[0] - $splitStart[0]; 
     $difMonths = $splitEnd[1] - $splitStart[1]; 
     $difDays = $splitEnd[2] - $splitStart[2]; 

     $retval = ($difDays > 0) ? $difMonths : $difMonths - 1; 
     $retval += $difYears * 12; 
    } 
    return $retval; 
} 

Nota: a diferencia de varias de las otras soluciones, esto no depende de las funciones de fecha agregado en PHP 5.3, ya que muchos hosts compartidos aún no están allí.

+0

Acabo de editar esta línea '' '$ retval = ($ difDays> 0)? $ difMonths: $ difMonths - 1; '' 'to' '' $ retval = ($ difDays> = 0)? $ difMonths: $ difMonths - 1; '' 'Entonces la diferencia entre 2017-01-01 y 2017-03-01 es solo 1 – jona303

14

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 hasta 01/05/2010 - 8 meses
  • 01.01.2013 - 31.03.2013 - 3 meses
  • 15.02.2013 - 15.04.2013 - 2 meses
  • 01.02.1985 - 31.12.2013 - 347 meses

Aviso: Debido al redondeo con los días, incluso se redondeará la mitad de un 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).
+0

buena solución, por ejemplo 01.06 - 01.07 da 0 mes (en m), pero usando días y redondeando funciona correctamente – Eddie

5

Solo quería agregar esto si alguien está buscando una solución simple que cuente cada mes tocado en lugar de meses completos, meses redondeados o algo así.

// Build example data 
$timeStart = strtotime("2003-10-17"); 
$timeEnd = strtotime("2004-03-24"); 
// Adding current month + all months in each passed year 
$numMonths = 1 + (date("Y",$timeEnd)-date("Y",$timeStart))*12; 
// Add/subtract month difference 
$numMonths += date("m",$timeEnd)-date("m",$timeStart); 

echo $numMonths; 
0
// get year and month difference 

$a1 = '20170401'; 

$a2 = '20160101' 

$yearDiff = (substr($a1, 0, 4) - substr($a2, 0, 4)); 

$monthDiff = (substr($a1, 4, 2) - substr($a2, 4, 2)); 

$fullMonthDiff = ($yearDiff * 12) + $monthDiff; 

// fullMonthDiff = 16 
0

Ésta es mi versión mejorada de @deceze respuesta:

/** 
* @param string $startDate 
* Current date is considered if empty string is passed 
* @param string $endDate 
* Current date is considered if empty string is passed 
* @param bool $unsigned 
* If $unsigned is true, difference is always positive, otherwise the difference might be negative 
* @return int 
*/ 
public static function diffInFullMonths($startDate, $endDate, $unsigned = false) 
{ 
    $diff = (new DateTime($startDate))->diff(new DateTime($endDate)); 
    $reverse = $unsigned === true ? '' : '%r'; 
    return ((int) $diff->format("{$reverse}%y") * 12) + ((int) $diff->format("{$reverse}%m")); 
} 
0

La mejor manera.

function getIntervals(DateTime $from, DateTime $to) 
{ 
    $intervals = []; 
    $startDate = $from->modify('first day of this month'); 
    $endDate = $to->modify('last day of this month'); 
    while($startDate < $endDate){ 
     $firstDay = $startDate->format('Y-m-d H:i:s'); 
     $startDate->modify('last day of this month')->modify('+1 day'); 
     $intervals[] = [ 
      'firstDay' => $firstDay, 
      'lastDay' => $startDate->modify('-1 second')->format('Y-m-d H:i:s'), 
     ]; 
     $startDate->modify('+1 second'); 
    } 
    return $intervals; 
} 
$dateTimeFirst = new \DateTime('2013-01-01'); 
$dateTimeSecond = new \DateTime('2013-03-31'); 
$interval = getIntervals($dateTimeFirst, $dateTimeSecond); 
print_r($interval); 

Resultado:

Array 
(
    [0] => Array 
     (
      [firstDay] => 2013-01-01 00:00:00 
      [lastDay] => 2013-01-31 23:59:59 
     ) 

    [1] => Array 
     (
      [firstDay] => 2013-02-01 00:00:00 
      [lastDay] => 2013-02-28 23:59:59 
     ) 

    [2] => Array 
     (
      [firstDay] => 2013-03-01 00:00:00 
      [lastDay] => 2013-03-31 23:59:59 
     ) 

) 
0

En mi caso necesitaba para contar meses y las sobras del día completo como mes también para construir una línea de etiquetas de gráficos.

/** 
* Calculate the difference in months between two dates 
* 
* @param \DateTime $from 
* @param \DateTime $to 
* @return int 
*/ 
public static function diffInMonths(\DateTime $from, \DateTime $to) 
{ 
    // Count months from year and month diff 
    $diff = $to->diff($from)->format('%y') * 12 + $to->diff($from)->format('%m'); 

    // If there is some day leftover, count it as the full month 
    if ($to->diff($from)->format('%d') > 0) $diff++; 

    // The month count isn't still right in some cases. This covers it. 
    if ($from->format('d') >= $to->format('d')) $diff++; 
} 
1
$datetime1 = date_create('2009-10-11'); 

$datetime2 = date_create('2013-1-13'); 

$interval = date_diff($datetime1, $datetime2); 

echo $interval->format('%a day %m month %y year'); 
+0

Día Mes Año Diferencia en php –