Saltar al contenido

¿Cómo calcular la diferencia entre dos fechas usando PHP?

Solución:

Sugiero usar objetos DateTime y DateInterval.

$date1 = new DateTime("2007-03-24");
$date2 = new DateTime("2009-06-26");
$interval = $date1->diff($date2);
echo "difference " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days "; 

// shows the total amount of days (not divided into years, months and days like above)
echo "difference " . $interval->days . " days ";

leer más php DateTime :: diff manual

Del manual:

A partir de PHP 5.2.2, los objetos DateTime se pueden comparar utilizando operadores de comparación.

$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2); // bool(false)
var_dump($date1 < $date2);  // bool(true)
var_dump($date1 > $date2);  // bool(false)

Use esto para código heredado (PHP <5.3). Para obtener una solución actualizada, consulte la respuesta de jurka a continuación

Puede usar strtotime () para convertir dos fechas a tiempo Unix y luego calcular el número de segundos entre ellas. A partir de esto, es bastante fácil calcular diferentes períodos de tiempo.

$date1 = "2007-03-24";
$date2 = "2009-06-26";

$diff = abs(strtotime($date2) - strtotime($date1));

$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

printf("%d years, %d months, %d daysn", $years, $months, $days);

Editar: Obviamente, la forma preferida de hacer esto es la que describe jurka a continuación. Mi código generalmente solo se recomienda si no tiene PHP 5.3 o superior.

Varias personas en los comentarios han señalado que el código anterior es solo una aproximación. Sigo creyendo que para la mayoría de los propósitos eso está bien, ya que el uso de un rango es más para proporcionar una idea de cuánto tiempo ha pasado o queda en lugar de proporcionar precisión; si desea hacer eso, simplemente envíe la fecha.

A pesar de todo eso, he decidido abordar las quejas. Si realmente necesita un rango exacto pero no tiene acceso a PHP 5.3, use el siguiente código (también debería funcionar en PHP 4). Este es un puerto directo del código que PHP usa internamente para calcular rangos, con la excepción de que no tiene en cuenta el horario de verano. Eso significa que está desfasado por una hora como máximo, pero excepto por eso, debería ser correcto.

= $end) 
        $result[$b] += intval($result[$a] / $adj);
        $result[$a] -= $adj * intval($result[$a] / $adj);
    

    return $result;


function _date_range_limit_days($base, $result)

    $days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    $days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    _date_range_limit(1, 13, 12, "m", "y", &$base);

    $year = $base["y"];
    $month = $base["m"];

    if (!$result["invert"]) 
        while ($result["d"] < 0) 
     else 
        while ($result["d"] < 0) 
            $leapyear = $year % 400 == 0 
    

    return $result;


function _date_normalize($base, $result)

    $result = _date_range_limit(0, 60, 60, "s", "i", $result);
    $result = _date_range_limit(0, 60, 60, "i", "h", $result);
    $result = _date_range_limit(0, 24, 24, "h", "d", $result);
    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    $result = _date_range_limit_days(&$base, &$result);

    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    return $result;


/**
 * Accepts two unix timestamps.
 */
function _date_diff($one, $two)

    $invert = false;
    if ($one > $two) 
        list($one, $two) = array($two, $one);
        $invert = true;
    

    $key = array("y", "m", "d", "h", "i", "s");
    $a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
    $b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));

    $result = array();
    $result["y"] = $b["y"] - $a["y"];
    $result["m"] = $b["m"] - $a["m"];
    $result["d"] = $b["d"] - $a["d"];
    $result["h"] = $b["h"] - $a["h"];
    $result["i"] = $b["i"] - $a["i"];
    $result["s"] = $b["s"] - $a["s"];
    $result["invert"] = $invert ? 1 : 0;
    $result["days"] = intval(abs(($one - $two)/86400));

    if ($invert) 
        _date_normalize(&$a, &$result);
     else 
        _date_normalize(&$b, &$result);
    

    return $result;


$date = "1986-11-10 19:37:22";

print_r(_date_diff(strtotime($date), time()));
print_r(_date_diff(time(), strtotime($date)));

El mejor curso de acción es usar PHP DateTime (y DateInterval) objetos. Cada fecha está encapsulada en un DateTime objeto, y luego se puede hacer una diferencia entre los dos:

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

los DateTime el objeto aceptará cualquier formato strtotime() haría. Si se necesita un formato de fecha aún más específico, DateTime::createFromFormat() se puede utilizar para crear el DateTime objeto.

Después de crear una instancia de ambos objetos, resta uno del otro con DateTime::diff().

$difference = $first_date->diff($second_date);

$difference ahora tiene un DateInterval objeto con la información de diferencia. A var_dump() Se ve como esto:

object(DateInterval)
  public 'y' => int 0
  public 'm' => int 0
  public 'd' => int 20
  public 'h' => int 6
  public 'i' => int 56
  public 's' => int 30
  public 'invert' => int 0
  public 'days' => int 20

Para formatear el DateInterval objeto, necesitaremos verificar cada valor y excluirlo si es 0:

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) 
    $result = "";
    if ($interval->y)  $result .= $interval->format("%y years "); 
    if ($interval->m)  $result .= $interval->format("%m months "); 
    if ($interval->d)  $result .= $interval->format("%d days "); 
    if ($interval->h)  $result .= $interval->format("%h hours "); 
    if ($interval->i)  $result .= $interval->format("%i minutes "); 
    if ($interval->s)  $result .= $interval->format("%s seconds "); 

    return $result;

Todo lo que queda ahora es llamar a nuestra función en el $differenceDateInterval objeto:

echo format_interval($difference);

Y obtenemos el resultado correcto:

20 días 6 horas 56 minutos 30 segundos

El código completo utilizado para lograr el objetivo:

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) 
    $result = "";
    if ($interval->y)  $result .= $interval->format("%y years "); 
    if ($interval->m)  $result .= $interval->format("%m months "); 
    if ($interval->d)  $result .= $interval->format("%d days "); 
    if ($interval->h)  $result .= $interval->format("%h hours "); 
    if ($interval->i)  $result .= $interval->format("%i minutes "); 
    if ($interval->s)  $result .= $interval->format("%s seconds "); 

    return $result;


$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

$difference = $first_date->diff($second_date);

echo format_interval($difference);

Aquí tienes las reseñas y puntuaciones

Eres capaz de patrocinar nuestra faena ejecutando un comentario o puntuándolo te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *