Apuntes php

PHP: Porque a veces necesitas un poco de caos en tu vida.

Obtener detalles con getdate()

getdate() devuelve un array con los componentes de una fecha:

<?php
print_r(getdate(mktime(0, 0, 0, 1, 1, 2005)));
?>

Sin argumentos, usa el timestamp actual:

<?php
$dateArray = getdate();
foreach ($dateArray as $key => $val) {
    echo "$key = $val\n";
}
?>

Salida (ejemplo):

    /*
    seconds: Segundos (0-59)
    minutes: Minutos (0-59)
    hours: Horas (0-23)
    mday: Día del mes (1-31)
    wday: Día de la semana (0=domingo, 6=sábado)
    mon: Mes (1-12)
    year: Año 1 (ejemplo: 2025)
    yday: Díaaño (0-365)
    weekday: Día de la semana (ejemplo: Monday)
    month: Mes (ejemplo: May)
    0: Timestamp original
    */

Parseando fechas con DateTime::createFromFormat()

La clase DateTime también ofrece el método createFromFormat() para parsear fechas que no están en un formato estándar:

<?php
$fechaString = "05/05/2025 18:15";
$fecha = DateTime::createFromFormat("d/m/Y H:i", $fechaString);
if ($fecha) {
    echo "Fecha parseada: " . $fecha->format("Y-m-d H:i:s") . "\n"; // 2025-05-05 18:15:00
} else {
    echo "Formato de fecha inválido\n";
}

$otraFechaString = "May-05-2025";
$otraFecha = DateTime::createFromFormat("M-d-Y", $otraFechaString);
if ($otraFecha) {
    echo "Otra fecha parseada: " . $otraFecha->format("Y-m-d") . "\n"; // 2025-05-05
} else {
    echo "Otro formato de fecha inválido\n";
}
?>

Comparando fechas con DateTime

Los objetos DateTime se pueden comparar directamente o usando el método diff():

<?php
$fecha1 = new DateTime("2025-05-05");
$fecha2 = new DateTime("2025-05-10");

if ($fecha1 < $fecha2) {
    echo "La fecha 1 es anterior a la fecha 2\n";
}

$diferencia = $fecha1->diff($fecha2);
echo "Diferencia: " . $diferencia->format("%R%a días\n"); // Diferencia: +5 días
?>

###Equivalentes MySQL

Formatos compatibles con MySQL: PHP

<?php
$mysqlDatetime = date("Y-m-d H:i:s"); // Ejemplo: 2025-05-05 18:10:50
$mysqlDate = date("Y-m-d"); // Ejemplo: 2025-05-05
$mysqlTime = date("H:i:s"); // Ejemplo: 18:10:50
?>

Obtener componentes con localtime()

localtime() devuelve un array indexado con los componentes de la fecha local. El primer parámetro (int) permite pasar un timestamp; el segundo parámetro (true|false) indica si queremos el resultado en array indexado numericamente o asociativo.

<?php
print_r(localtime(time(), true));
/*
Array
(
    [tm_sec] => 37
    [tm_min] => 51
    [tm_hour] => 9
    [tm_mday] => 7
    [tm_mon] => 5
    [tm_year] => 125
    [tm_wday] => 6
    [tm_yday] => 157
    [tm_isdst] => 0
)
*/
?>

Analizar con date_parse()

<?php
print_r(date_parse("2025-06-07 14:30:00"));
/*
Array
(
    [year] => 2025
    [month] => 6
    [day] => 7
    [hour] => 14
    [minute] => 30
    [second] => 0
    [fraction] => 0
    [warning_count] => 0
    [warnings] => Array
        (
        )

    [error_count] => 0
    [errors] => Array
        (
        )

    [is_localtime] =>
)

*/
?>

gettimeofday()

gettimeofday() devuelve información precisa sobre el momento actual:

<?php
print_r(gettimeofday());
/*
Array
(
    [sec] => 1749290587
    [usec] => 986559
    [minuteswest] => 0
    [dsttime] => 0
)
*/
?>

Esta función admite un parámetro booleano. Si pasamos true devuelve el resultado en forma decimal

Obtener partes individuales con idate()

<?php
echo idate("Y"); // Año actual
?>

Fechas en UTC con gmdate()

<?php
echo gmdate("Y-m-d H:i:s");
?>

Amanecer y atardecer

<?php
echo date_sunrise(time(), SUNFUNCS_RET_STRING, 40.4168, -3.7038, 90, 1);
echo date_sunset(time(), SUNFUNCS_RET_STRING, 40.4168, -3.7038, 90, 1);
?>

Configuración regional con setlocale()

<?php
setlocale(LC_TIME, "es_ES.UTF-8");
echo strftime("%A %d de %B de %Y"); // Obsoleto desde PHP 8.1
?>

Formato internacional con IntlDateFormatter

<?php
$fmt = new IntlDateFormatter('es_ES', IntlDateFormatter::FULL, IntlDateFormatter::NONE);
echo $fmt->format(new DateTime("2025-06-07"));
?>

hora en castellano ?


                <?php
                $formatter = new IntlDateFormatter(
                        'es_ES',
                        IntlDateFormatter::FULL,
                        IntlDateFormatter::SHORT,
                        'Europe/Madrid'
                );
                echo $formatter‐>format(new DateTime());
                // sábado, 7 de junio de 2025, 11:21
                ?>
                

DateTime::createFromFormat()

<?php
$dt = DateTime::createFromFormat("d-m-Y", "07-06-2025");
echo $dt->format("Y/m/d");
?>

Diferencia entre fechas

<?php
$inicio = new DateTime("2025-06-01");
$fin = new DateTime("2025-06-06");
$intervalo = $inicio->diff($fin);
echo $intervalo->days . " días";
?>

Zonas horarias

<?php
$dt = new DateTime("now", new DateTimeZone("UTC"));
echo $dt->format("Y-m-d H:i:s T");
print_r(DateTimeZone::listIdentifiers());
date_default_timezone_set("Europe/Madrid");
?>

Errores Comunes al Trabajar con Fechas

Estos son los errores más frecuentes que cometen los principiantes. Aprende a evitarlos desde el inicio:

1. No establecer la zona horaria

<?php
// PROBLEMA: El servidor puede estar en cualquier zona horaria
echo date("Y-m-d H:i:s"); // ¿Qué hora es realmente?

// SOLUCIÓN: Siempre establece la zona horaria al inicio
date_default_timezone_set("UTC"); // O la zona que necesites
echo date("Y-m-d H:i:s"); // Ahora sabemos que es UTC
?>

2. Confundir formatos de fecha

<?php
// PROBLEMA: strtotime() puede interpretar mal
$fecha = "01/02/2025"; // ¿Es 1 de febrero o 2 de enero?
$timestamp = strtotime($fecha);
echo date("Y-m-d", $timestamp); // Resultado impredecible

// SOLUCIÓN: Usa formatos claros
$fecha = "2025-02-01"; // Formato ISO: año-mes-día
$timestamp = strtotime($fecha);
echo date("Y-m-d", $timestamp); // 2025-02-01 (claro y predecible)
?>

3. No validar fechas de formularios

<?php
// PROBLEMA: Confiar ciegamente en lo que envía el usuario
$dia = $_POST['dia']; // Usuario escribió "32"
$mes = $_POST['mes']; // Usuario escribió "13"
$año = $_POST['año']; // Usuario escribió "2025"

$timestamp = mktime(0, 0, 0, $mes, $dia, $año); // ¡Fecha inválida!

// SOLUCIÓN: Validar siempre con checkdate()
$dia = (int)$_POST['dia'];
$mes = (int)$_POST['mes'];
$año = (int)$_POST['año'];

if (checkdate($mes, $dia, $año)) {
    $timestamp = mktime(0, 0, 0, $mes, $dia, $año);
    echo "Fecha válida: " . date("Y-m-d", $timestamp);
} else {
    echo "Error: Fecha inválida";
}
?>

4. Usar strtotime() con fechas en español

<?php
// PROBLEMA: strtotime() solo entiende inglés
$fecha = strtotime("próximo lunes"); // No funciona
$fecha = strtotime("mañana"); // No funciona

// SOLUCIÓN: Usar términos en inglés
$mañana = strtotime("tomorrow");
$proximoLunes = strtotime("next Monday");
$semanaQueViene = strtotime("+1 week");

echo "Mañana: " . date("Y-m-d", $mañana) . "\n";
echo "Próximo lunes: " . date("Y-m-d", $proximoLunes) . "\n";
?>

5. Comparar fechas como strings

<?php
// PROBLEMA: Comparar fechas como texto
$fecha1 = "2025-6-7";   // Sin ceros
$fecha2 = "2025-06-07"; // Con ceros
if ($fecha1 == $fecha2) {
    echo "Fechas iguales";
} else {
    echo "Fechas diferentes"; // ¡Pero son el mismo día!
}

// SOLUCIÓN: Convertir a timestamps y comparar
$timestamp1 = strtotime("2025-6-7");
$timestamp2 = strtotime("2025-06-07");
if ($timestamp1 == $timestamp2) {
    echo "Fechas iguales"; // ¡Correcto!
} else {
    echo "Fechas diferentes";
}
?>

6. Olvidar los años bisiestos

<?php
// PROBLEMA: Asumir que febrero siempre tiene 28 días
function diasEnFebrero($año) {
    return 28; // ¡Error!
}

// SOLUCIÓN: Usar checkdate() o calcular correctamente
function diasEnFebreroCorrectos($año) {
    if (checkdate(2, 29, $año)) {
        return 29; // Año bisiesto
    } else {
        return 28; // Año normal
    }
}

echo "Febrero 2024: " . diasEnFebreroCorrectos(2024) . " días\n"; // 29 días
echo "Febrero 2025: " . diasEnFebreroCorrectos(2025) . " días\n"; // 28 días
?>

7. No considerar la diferencia entre date() y gmdate()

<?php
// Configuramos zona horaria local
date_default_timezone_set("Europe/Madrid");

$timestamp = time();

// CONFUSIÓN: No saber cuál usar
echo "date(): " . date("Y-m-d H:i:s", $timestamp) . "\n";     // Hora local (Madrid)
echo "gmdate(): " . gmdate("Y-m-d H:i:s", $timestamp) . "\n"; // Hora UTC

// REGLA SIMPLE:
// - date() para mostrar al usuario (su zona horaria)
// - gmdate() para guardar en base de datos (siempre UTC)
?>

8. Formatear fechas incorrectamente

<?php
$timestamp = time();

// PROBLEMA: Confundir los modificadores
echo date("Y-M-D", $timestamp); // M = May, D = Mon (no es lo que queremos)
echo date("y-m-d", $timestamp); // y = 25 (año de 2 dígitos)

// SOLUCIÓN: Usar los modificadores correctos
echo date("Y-m-d", $timestamp); // 2025-06-07 (formato estándar)
echo date("d/m/Y", $timestamp); // 07/06/2025 (formato español)
echo date("j \\d\\e F \\d\\e Y", $timestamp); // 7 de June de 2025

// Recuerda: escapar letras literales con \
?>

Consejos para Principiantes

  • Siempre establece la zona horaria con date_default_timezone_set() al inicio de tu script
  • Usa timestamps para cálculos y convierte a formato legible solo para mostrar
  • Valida las fechas que vienen de formularios con checkdate()
  • Guarda fechas en UTC en la base de datos, convierte a zona local para mostrar
  • Usa formatos estándar como "Y-m-d" para evitar ambigüedades
  • Prueba siempre con años bisiestos, cambios de horario y fechas límite

Caso Práctico: Mostrar Fechas de Posts en Castellano

El primer problema por el que la mayoría de desarrolladores necesitan aprender a manejar fechas es porque quieren mostrar la fecha de publicación de un post en su blog en castellano. En lugar de "Monday, 7 June 2025" quieren mostrar "lunes, 7 de junio de 2025".

Como strftime() está obsoleto y puede no funcionar en todos los servidores, esta es la solución recomendada actual:

<?php
function fechaEnCastellano($timestamp) {
    // Arrays con los nombres en castellano
    $meses = [
        1 => 'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
        'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'
    ];

    $dias = [
        1 => 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo'
    ];

    $fecha = getdate($timestamp);
    $dia_semana = $dias[$fecha['wday'] == 0 ? 7 : $fecha['wday']]; // Domingo = 0, lo cambiamos a 7
    $dia = $fecha['mday'];
    $mes = $meses[$fecha['mon']];
    $año = $fecha['year'];

    return "$dia_semana, $dia de $mes de $año";
}

// Ejemplo de uso en un blog
$fechaPost = strtotime("2025-06-07"); // Fecha del post desde la base de datos
echo "Publicado el " . fechaEnCastellano($fechaPost);
// Resultado: "Publicado el sábado, 7 de junio de 2025"

// Para formato más corto
function fechaCortaCastellano($timestamp) {
    $meses = [
        1 => 'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
        'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'
    ];

    $fecha = getdate($timestamp);
    return $fecha['mday'] . ' de ' . $meses[$fecha['mon']] . ' de ' . $fecha['year'];
}

echo fechaCortaCastellano($fechaPost); // "7 de junio de 2025"
?>

¿Por qué esta solución?

  • Funciona en cualquier servidor PHP sin dependencias externas
  • No requiere configuración de locales del sistema operativo
  • Es más rápida que IntlDateFormatter para casos simples
  • Tienes control total sobre el formato y las palabras utilizadas
  • Es fácil de modificar y mantener

Esta es la solución más práctica para la mayoría de casos

TOP