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 $difference
DateInterval
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.