DateInterval y DatePeriod en PHP: calcular diferencias entre fechas y rangos

DateInterval representa una duración (un período de tiempo como «3 meses y 5 días»), mientras que DatePeriod permite iterar sobre un rango de fechas con un intervalo fijo. Combinados con DateTimeImmutable, cubren prácticamente cualquier necesidad de cálculo de fechas en PHP.

DateInterval: crear duraciones

La especificación de un DateInterval sigue el formato ISO 8601: P (de period) seguido de los componentes de fecha y luego T seguido de los componentes de tiempo:

<?php
$tresAnios   = new DateInterval('P3Y');       // 3 años
$unMes       = new DateInterval('P1M');       // 1 mes
$diezDias    = new DateInterval('P10D');      // 10 días
$dosHoras    = new DateInterval('PT2H');      // 2 horas (T antes de componentes de tiempo)
$completo    = new DateInterval('P1Y2M3DT4H5M6S'); // 1a 2m 3d 4h 5min 6s

// Acceder a los componentes
echo $completo->y; // 1  (años)
echo $completo->m; // 2  (meses)
echo $completo->d; // 3  (días)
echo $completo->h; // 4  (horas)
echo $completo->i; // 5  (minutos)
echo $completo->s; // 6  (segundos)
?>

diff(): calcular la diferencia entre dos fechas

El método diff() de DateTimeImmutable devuelve un DateInterval con la diferencia entre dos fechas:

<?php
$inicio = new DateTimeImmutable('2026-01-01');
$fin    = new DateTimeImmutable('2026-07-22');

$diff = $inicio->diff($fin);

echo $diff->y . ' años, ';    // 0 años
echo $diff->m . ' meses, ';  // 6 meses
echo $diff->d . ' días';     // 21 días
echo "n";
echo $diff->days . ' días totales'; // 202 días totales (propiedad especial)
?>

La propiedad $diff->days devuelve el total de días entre las dos fechas, independientemente de años y meses. Es la forma más fiable de calcular una diferencia en días.

Calcular la edad de un usuario

<?php
function calcularEdad(string $nacimiento): int
{
    $fechaNac = new DateTimeImmutable($nacimiento);
    $hoy      = new DateTimeImmutable('today');
    return $fechaNac->diff($hoy)->y; // propiedad y = años completos
}

echo calcularEdad('1990-07-22') . ' años'; // 35 años (en 2026)
echo calcularEdad('1990-07-25') . ' años'; // 35 años (cumple en 3 días, aún no)
?>

Tiempo relativo en interfaces de usuario

<?php
function tiempoRelativo(DateTimeImmutable $fecha): string
{
    $ahora = new DateTimeImmutable();
    $diff  = $fecha->diff($ahora);

    if ($diff->days === 0) {
        if ($diff->h === 0) {
            return $diff->i . ' minutos';
        }
        return $diff->h . ' horas';
    }
    if ($diff->days < 7) {
        return $diff->days . ' días';
    }
    if ($diff->days < 30) {
        return (int) ($diff->days / 7) . ' semanas';
    }
    if ($diff->m < 12) {
        return $diff->m . ' meses';
    }
    return $diff->y . ' años';
}

$publicado = new DateTimeImmutable('-3 hours');
echo 'Hace ' . tiempoRelativo($publicado); // Hace 3 horas
?>

DatePeriod: rangos de fechas para calendarios

DatePeriod genera una secuencia de fechas iterables entre un inicio y un fin (o un número de recurrencias) separadas por un intervalo:

<?php
// Todos los días de julio de 2026
$inicio   = new DateTimeImmutable('2026-07-01');
$fin      = new DateTimeImmutable('2026-08-01');
$intervalo = new DateInterval('P1D'); // 1 día

$periodo = new DatePeriod($inicio, $intervalo, $fin);

foreach ($periodo as $dia) {
    echo $dia->format('d/m/Y') . "n";
}
// 01/07/2026, 02/07/2026, ... 31/07/2026
?>

Generación de slots de agenda

<?php
// Slots de 30 minutos entre las 9:00 y las 14:00
$apertura = new DateTimeImmutable('2026-07-22 09:00:00');
$cierre   = new DateTimeImmutable('2026-07-22 14:00:00');
$slot     = new DateInterval('PT30M'); // 30 minutos

$agenda = new DatePeriod($apertura, $slot, $cierre);

foreach ($agenda as $hora) {
    echo $hora->format('H:i') . "n";
}
// 09:00, 09:30, 10:00, 10:30, 11:00, 11:30, 12:00, 12:30, 13:00, 13:30
?>

Errores frecuentes

  • Confundir $diff->m con el total de meses: $diff->m son los meses restantes tras calcular los años. Para el total de meses, usa $diff->y * 12 + $diff->m.
  • DatePeriod no incluye la fecha de fin: si quieres incluirla, usa DatePeriod::INCLUDE_END_DATE (disponible desde PHP 8.2) o añade un día extra al límite.
  • Zona horaria en diff(): si las dos fechas tienen zonas horarias distintas, diff() convierte internamente a UTC antes de calcular, lo que puede dar resultados inesperados en fechas con cambio de horario.

La documentación de DateInterval y la de DatePeriod detallan todos los constructores y opciones disponibles.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP