Gestión de Marcas de Tiempo en PHP: Conversiones y Formatos Relativos

Introducción a la Manipulación de Fechas con Marcas de Tiempo en PHP

Las marcas de tiempo, o "timestamps", son un mecanismo fundamental en PHP para manejar fechas y horas. Representan un punto en el tiempo como un entero, generalmente el número de segundos transcurridos desde la Época Unix (1 de enero de 1970 00:00:00 UTC). Este enfoque numérico simplifica las operaciones de comparación y cálculo de intervalos. Exploraremos cómo PHP, a través de funciones como strtotime() y date(), facilita la conversión entre formatos de fecha y la presentación de tiempos de manera amigable.

1. Conversión de Cadenas de Fecha a Marcas de Tiempo Unix con strtotime()

La función strtotime() de PHP es una herramienta increíblemente versátil que puede analizar una amplia gama de cadenas de texto en inglés para generar la marca de tiempo Unix correspondiente. Esto incluye fechas absolutas y descripciones relativas.

Ejemplo de obtención de la marca de tiempo para una fecha específica:

<?php
// Definimos una fecha específica
$fechaEspecifica = "2024-01-01";

// Convertimos la cadena de fecha a una marca de tiempo Unix
$marcaTiempoGenerada = strtotime($fechaEspecifica);

echo "La marca de tiempo Unix para el " . $fechaEspecifica . " es: " . $marcaTiempoGenerada;
// Ejemplo de salida: La marca de tiempo Unix para el 2024-01-01 es: 1704067200
?>

2. Formateo de Marcas de Tiempo a Cadenas Legbiles con date()

Una vez que tenemos una marca de tiempo, la función date() permite formatearla en una cadena de fecha y hora legible. Requiere una cadena de formato y, opcionalmente, la marca de tiempo a formatear (si se omite, usa la marca de tiempo actual).

<?php
// Una marca de tiempo de ejemplo
$tsEjemplo = 1228348800; // Corresponde a 2008-12-04 00:00:00 UTC

// Formateamos la marca de tiempo en un formato YYYY-MM-DD HH:MM:SS
$fechaLegible = date('Y-m-d H:i:s', $tsEjemplo);

echo "La marca de tiempo " . $tsEjemplo . " se formatea como: " . $fechaLegible;
// Ejemplo de salida: La marca de tiempo 1228348800 se formatea como: 2008-12-04 00:00:00
?>

3. Obtención de Marcas de Tiempo para Puntos Temporales Comunes

Con frecuencia, necesitamos la marca de tiempo para el inicio del día actual (medianoche) o del día siguiente. Esto se puede lograr combinando date() y strtotime().

  • Marca de tiempo del inicio del día actual (medianoche):

    <?php
    $inicioHoy = strtotime(date("Y-m-d", time()));
    echo "Marca de tiempo del inicio del día actual: " . $inicioHoy;
    // Ejemplo: Marca de tiempo del inicio del día actual: 1700966400 (para 2023-11-26 00:00:00)
    ?>
    
  • Marca de tiempo del inicio del día siguiente (medianoche de mañana):

    <?php
    // Usando strtotime directamente con 'tomorrow' es lo más sencillo
    $inicioManana = strtotime("tomorrow");
    echo "Marca de tiempo del inicio del día de mañana: " . $inicioManana;
    // Ejemplo: Marca de tiempo del inicio del día de mañana: 1701052800 (para 2023-11-27 00:00:00)
    ?>
    

4. Uso de strtotime() con Expresiones de Tiempo Relativo

La flexibilidad de strtotime() brilla al interpretar descripciones relativas como "+1 day", "-1 month", "next Monday". Esto simplifica el cálculo de fechas futuras o pasadas sin aritmética manual de segundos.

Veamos varios ejemplos, mostrando la hora actual para contexto:

<?php
// Mostramos la hora actual como referencia
echo "Momento actual: " . date("Y-m-d H:i:s", time()) . "<br><br>";

// a) Un día en el futuro:
echo "Fecha y hora en +1 día: " . date("Y-m-d H:i:s", strtotime("+1 day")) . "<br>";

// b) Un día en el pasado:
echo "Fecha y hora en -1 día: " . date("Y-m-d H:i:s", strtotime("-1 day")) . "<br>";

// c) Una semana en el futuro:
echo "Fecha y hora en +1 semana: " . date("Y-m-d H:i:s", strtotime("+1 week")) . "<br>";

// d) Una semana en el pasado:
echo "Fecha y hora en -1 semana: " . date("Y-m-d H:i:s", strtotime("-1 week")) . "<br>";

// e) El próximo jueves:
echo "Fecha y hora del próximo jueves: " . date("Y-m-d H:i:s", strtotime("next Thursday")) . "<br>";

// f) El jueves pasado:
echo "Fecha y hora del jueves pasado: " . date("Y-m-d H:i:s", strtotime("last Thursday")) . "<br>";
?>

5. Funciones Personalizadas para Mostrar Tiempos "Amigables"

Para mejorar la experiencia del usuario, es común mostrar las fechas de forma relativa (por ejemplo, "hace 10 minutos", "ayer", "el 15 de marzo"). A continuación, presentamos funciones PHP para lograr esto, ajustando la salida según la cercanía de la fecha.

Función 1: obtenerTiempoLegible()

Esta función evalúa la diferencia entre una marca de tiempo dada y el momento actual para generar una cadena de texto relativa. Incluye manejo para "hoy", "ayer" y "anteayer", además de formatos de fecha más completos para tiempos más antiguos.

<?php
function obtenerTiempoLegible(int $tsReferencia): string
{
    $tsActual = time();
    $diferenciaSegundos = $tsActual - $tsReferencia;

    // Si el tiempo es futuro o si la marca de tiempo es inválida, se devuelve el formato completo
    if ($diferenciaSegundos < 0 || $tsReferencia === false) {
        return date("Y-m-d H:i", $tsReferencia);
    }

    if ($diferenciaSegundos < 60) {
        return ($diferenciaSegundos === 0) ? "justo ahora" : $diferenciaSegundos . " segundos atrás";
    } elseif ($diferenciaSegundos < 3600) { // Menos de 1 hora
        return floor($diferenciaSegundos / 60) . " minutos atrás";
    } elseif ($diferenciaSegundos < 86400) { // Menos de 24 horas
        return floor($diferenciaSegundos / 3600) . " horas atrás";
    }

    // Comprobaciones para "hoy", "ayer", "anteayer"
    $fechaRefDia = date('Ymd', $tsReferencia);
    $fechaActualDia = date('Ymd', $tsActual);
    $fechaAyerDia = date('Ymd', strtotime('-1 day', $tsActual));
    $fechaAnteayerDia = date('Ymd', strtotime('-2 days', $tsActual));

    if ($fechaRefDia == $fechaActualDia) {
        return "hoy a las " . date('H:i', $tsReferencia);
    } elseif ($fechaRefDia == $fechaAyerDia) {
        return "ayer a las " . date('H:i', $tsReferencia);
    } elseif ($fechaRefDia == $fechaAnteayerDia) {
        return "anteayer a las " . date('H:i', $tsReferencia);
    }

    // Si es del mismo año, omitir el año en el formato
    if (date('Y', $tsReferencia) == date('Y', $tsActual)) {
        return date('d M H:i', $tsReferencia); // Ej: 26 Nov 15:30
    }

    // Para fechas más antiguas, se devuelve el formato completo con año
    return date('Y-m-d H:i', $tsReferencia);
}

// Ejemplos de uso:
echo "Hace 10 segundos: " . obtenerTiempoLegible(time() - 10) . "<br>";
echo "Hace 30 minutos: " . obtenerTiempoLegible(time() - 1800) . "<br>";
echo "Hace 5 horas: " . obtenerTiempoLegible(time() - 18000) . "<br>";
echo "Ayer a las 09:45: " . obtenerTiempoLegible(strtotime('yesterday 09:45')) . "<br>";
echo "Anteayer por la tarde: " . obtenerTiempoLegible(strtotime('-2 days 17:00')) . "<br>";
echo "El 15 de marzo de este año: " . obtenerTiempoLegible(strtotime('2023-03-15 11:20')) . "<br>";
echo "El 1 de enero del año pasado: " . obtenerTiempoLegible(strtotime('2022-01-01 10:00')) . "<br>";
echo "Una fecha futura: " . obtenerTiempoLegible(strtotime('+5 days 14:00')) . "<br>";
?>

Función 2: formatearIntervaloCorto()

Esta es una función más concisa para mostrar intervalos de tiempo, ideal para feeds o notificaciones donde el espacio es limitado. Utiliza abreviaturas para segundos y minutos, y muestra "hoy" o "ayer" antes de recurrir a formatos de fecha más largos.

<?php
function formatearIntervaloCorto(int $marcaTiempo): string
{
    $momentoActual = time();
    $diferencia = $momentoActual - $marcaTiempo;
    
    // Convertir a objetos DateTime para comparaciones de día más precisas
    $dtMarcaTiempo = new DateTime('@' . $marcaTiempo);
    $dtMomentoActual = new DateTime('@' . $momentoActual);

    // Manejar tiempos futuros o inválidos
    if ($diferencia < 0 || $marcaTiempo === false) {
        return $dtMarcaTiempo->format('Y-m-d H:i');
    }

    if ($diferencia < 60) {
        return $diferencia . "s atrás";
    } elseif ($diferencia < 3600) { // Menos de 1 hora
        return floor($diferencia / 60) . "m atrás";
    } elseif ($dtMarcaTiempo->format('Ymd') == $dtMomentoActual->format('Ymd')) { // Mismo día
        return "hoy " . $dtMarcaTiempo->format('H:i');
    } elseif ($dtMarcaTiempo->format('Ymd') == date('Ymd', strtotime('-1 day', $momentoActual))) { // Ayer
        return "ayer " . $dtMarcaTiempo->format('H:i');
    } elseif ($dtMarcaTiempo->format('Y') == $dtMomentoActual->format('Y')) { // Mismo año
        return $dtMarcaTiempo->format('d M H:i'); // Ej: 26 Nov 15:30
    } else { // Año diferente
        return $dtMarcaTiempo->format('Y-m-d H:i');
    }
}

// Ejemplos de uso:
echo "Hace 20 segundos: " . formatearIntervaloCorto(time() - 20) . "<br>";
echo "Hace 50 minutos: " . formatearIntervaloCorto(time() - 3000) . "<br>";
echo "Hoy a las 14:00: " . formatearIntervaloCorto(strtotime('today 14:00')) . "<br>";
echo "Ayer a medianoche: " . formatearIntervaloCorto(strtotime('yesterday 00:00')) . "<br>";
echo "El 1 de mayo de este año: " . formatearIntervaloCorto(strtotime('2023-05-01 10:30')) . "<br>";
echo "El 31 de diciembre del año pasado: " . formatearIntervaloCorto(strtotime('2022-12-31 23:59')) . "<br>";
?>

Etiquetas: PHP timestamp Date strtotime relative time

Publicado el 8-28 13:32