Fechas bonitas y funcionales en PHP

Fechas bonitas y funcionales en PHP

Primero quiero hacer mención a una nota que hay en el manual oficial de PHP “PHP.net”.

Nota:
Las fechas en los formatos m/d/y o d-m-y no son ambiguas al observar el separador entre los distintos componentes: si el separador es una barra (/), se asume el formato norteamericano m/d/y; mientras que si el separador es un guión (-) o un punto (.), se asume el formato europeo d-m-y.
Para evitar esta ambigüedad potencial es mejor usar fechas ISO 8601 (YYYY-MM-DD).

Con esto entiendo que si pones una fecha así:

$fecha = "01-02-15"; // 1 de Febrero de 2015 | d-m-y.

Al estar con guiones, PHP lo interpreta como formato Europeo, todo bien. Pero si esa misma fecha la pones en formato Europeo con barras, PHP la interpretará como formato Americano, osea que la habremos “liao parda”.

$fecha = "01/02/15"; // 2 de Enero de 2015 | m/d/y.

Por lo tanto, hagamos caso al manual oficial de PHP, y siempre que podamos, usemos el formato ISO 8601(AAAA-MM-DD). A menos que creas que es lo mismo “1 de Febrero de 2015″ y “2 de Enero de 2015″. :)

Muchas veces necesitamos mostrar fechas en la web, y como no?, necesitamos que sea bonita, o agradable a la vista, algo como: “Viernes, 23 de Enero de 2015”. Pero nos encontramos con un pequeño problema, que al intentar tratar esa fecha no podemos con ese bonito formato, ya que PHP no lo reconoce como fecha, y tenemos que transformarla, y entonces podremos tratarla y almacenarla en bases de datos.

El formato de fecha en MySql es AAAA-MM-DD, algo como “2015-01-23”, y si le damos a MySql algo que no sea así, nos insertará esto 0000-00-00 en la base de datos.

PHP nos provee de funciones para poder tratar las fechas de forma sencilla, pero como ya he comentado antes, estas tienen que estar en un formato reconocible. Ahora veremos como podemos transformar la fecha de bonita a funcional y viceversa.

Podemos empezar por transformar una fecha recogida de una base de datos, en este formato bonito para mostrarla.

Supongamos que la tenemos en la variable $fecha, como la acabamos de coger de una base de datos, su formato será “2015-01-23”, así que para convertirla a “Viernes, 23 de Enero de 2015” usaremos la función date() de PHP para saber el día de la semana que corresponde a esa fecha, esa misma función nos dará el día de mes y el año, y con un array con los días de la semana y otro con los meses en letra transformaremos fácilmente ese “01” a “Enero” en los meses y el “1” a “Lunes” en los días.

$fecha = "2015-01-23";

Empezamos por crear el array de los días de la semana.

$dia_semana[1] = "Lunes";
$dia_semana[2] = "Martes";
$dia_semana[3] = "Miércoles";
$dia_semana[4] = "Jueves";
$dia_semana[5] = "Viernes";
$dia_semana[6] = "Sábado";
$dia_semana[7] = "Domingo";

Y seguimos con el array de los meses.

$mes[1] = "Enero";
$mes[2] = "Febrero";
$mes[3] = "Marzo";
$mes[4] = "Abril";
$mes[5] = "Mayo";
$mes[6] = "Junio";
$mes[7] = "Julio";
$mes[8] = "Agosto";
$mes[9] = "Septiembre";
$mes[10] = "Octubre";
$mes[11] = "Noviembre";
$mes[12] = "Diciembre";

En realidad la clave no es necesaria, pero si no la ponemos tenemos que tener en cuenta que los arrays siempre comienzan por cero, por lo que sería algo así:

$mes[] = "Enero"; // Equivale a $mes[0] = "Enero";
$mes[] = "Febrero"; // Equivale a $mes[1] = "Febrero";

Así que el mes “01” nos devolverá “Febrero”, entonces para que funcione correctamente le tendríamos que restar 1 a la clave, algo así:

$mes[clave – 1]; // La clave "01" menos 1 es 0 y ya correspondería con el valor "Enero".

Aún así, nos podemos encontrar con el problema de que el array $mes ya exista, entonces al crear un nuevo elemento sin la clave, este se indexará con el número que le corresponda según su posición en el array, por ejemplo, supongamos que tenemos el array $mes con cuatro elementos:

$mes[0] = "Enero";
$mes[1] = "Febrero";
$mes[2] = "Marzo";
$mes[3] = "Abril";

Ahora insertamos un nuevo elemento sin clave:

$mes[] = "Enero";

Este se indexará igual que si hubiéramos puesto:

$mes[4] = "Enero";

Por eso usaremos claves numéricas al crear el array, así evitaremos estos pequeños inconvenientes. En muchas ocasiones nos irá muy bien insertar elementos en nuestros arrays sin poner clave, ya que así no importa cuantos elementos tenga, siempre se insertará al final de este, pero este no es el caso.

Entonces, ya tenemos creados los arrays $dia_semana y $mes, y ahora las siguientes líneas serían algo así:

$ts_fecha = strtotime($fecha); // Convertimos la fecha en TimeStamp para poder trabajarla con date().
$numero_dia_semana = date("N", $ts_fecha); // Extraemos el número de día de la semana, de 1 a 7.
$numero_mes = date("n", $ts_fecha); // Extraemos el número del mes sin cero inicial, de 1 a 12.
$fecha_formateada = $dia_semana[$numero_dia_semana] . ", " . date("j", $ts_fecha) . " de " . $mes[$numero_mes] . " de " . date("Y", $ts_fecha); // Lo juntamos todo para formar la cadena.

Esto sería en cuatro líneas, pero podemos hacerlo en unas cuantas líneas más, que aunque tiene más código, se ve más claro:

$ts_fecha = strtotime($fecha); // Convertimos la fecha en TimeStamp para poder trabajarla con date().
$numero_dia_semana = date("N", $ts_fecha); // Extraemos el número de día de la semana, de 1 a 7.
$dia_mes = date("j", $ts_fecha); // Extraemos el número de día del mes sin cero inicial, de 1 a 31.
$numero_mes = date("n", $ts_fecha); // Extraemos el número del mes sin cero inicial, de 1 a 12.
$ano = date("Y", $ts_fecha); // Extraemos el número del año en cuatro dígitos.
$fecha_formateada = $dia_semana[$numero_dia_semana] . ", " . $dia_mes . " de " . $mes[$numero_mes] . " de " . $ano; // Lo juntamos todo para formar la cadena.

En los dos casos anteriores el resultado es exactamente el mismo:

$fecha_formateada = "Viernes, 23 de Enero de 2015";

Tengo que reconocer que yo suelo usar el primer método, para no usar tantas variables intermedias, pero creo que es más inteligente usar el segundo, ya que todo lo que sea facilitar la lectura se agradece enormemente cuando tienes que repasar el código una y otra vez buscando ese error que te deja en ocasiones clavado varias horas (Tomo nota).

En definitiva, el código para transformar una fecha tomada de una base de datos MySql en algo agradable a la vista (2015-01-23 —-> Viernes, 23 de Enero de 2015) quedaría en esto:

$dia_semana[1] = "Lunes";
$dia_semana[2] = "Martes";
$dia_semana[3] = "Miércoles";
$dia_semana[4] = "Jueves";
$dia_semana[5] = "Viernes";
$dia_semana[6] = "Sábado";
$dia_semana[7] = "Domingo";

$mes[1] = "Enero";
$mes[2] = "Febrero";
$mes[3] = "Marzo";
$mes[4] = "Abril";
$mes[5] = "Mayo";
$mes[6] = "Junio";
$mes[7] = "Julio";
$mes[8] = "Agosto";
$mes[9] = "Septiembre";
$mes[10] = "Octubre";
$mes[11] = "Noviembre";
$mes[12] = "Diciembre";

$ts_fecha = strtotime($fecha); // Convertimos la fecha en TimeStamp para poder trabajarla con date().

$numero_dia_semana = date("N", $ts_fecha); // Extraemos el número de día de la semana, de 1 a 7.
$dia_mes = date("j", $ts_fecha); // Extraemos el número de día del mes sin cero inicial, de 1 a 31.
$numero_mes = date("n", $ts_fecha); // Extraemos el número del mes sin cero inicial, de 1 a 12.
$ano = date("Y", $ts_fecha); // Extraemos el número del año en cuatro dígitos.

$fecha_formateada = $dia_semana[$numero_dia_semana] . ", " . $dia_mes . " de " . $mes[$numero_mes] . " de " . $ano; // Lo juntamos todo para formar la cadena.

Ahora vamos a hacer lo contrario, imaginemos que tenemos la fecha en ese formato bonito y queremos guardarla en una base de datos MySql. Veamos como transformarla.

Supongamos que en la variable $fecha tenemos esto:

$fecha = "Viernes, 23 de Enero de 2015";

No podemos usar la función date() ya que la fecha en formato bonito no es reconocida como tal por PHP, así que usaremos la función explode(), que lo que hace es dividir una cadena y agregar los elementos resultantes en un array, las divisiones las hace a través de un patrón definido, me explico:

$array_fecha = explode(" ", $fecha); //Patrón de búsqueda, un espacio en blanco.

Nos daría como resultado esto:

$array_fecha[0] = "Viernes,";
$array_fecha[1] = "23";
$array_fecha[2] = "de";
$array_fecha[3] = "Enero";
$array_fecha[4] = "de";
$array_fecha[5] = "2015";

El patrón a buscar para dividir por ahí es un espacio, y el resultado nos deja bastante claro como tenemos que continuar. Igual que antes, haremos un array para convertir los meses de texto a números. Para el día y el año no hace falta, ya los tenemos en $array_fecha[1] y $array_fecha[5].

$mes["Enero"] = "01";
$mes["Febrero"] = "02";
$mes["Marzo"] = "03";
$mes["Abril"] = "04";
$mes["Mayo"] = "05";
$mes["Junio"] = "06";
$mes["Julio"] = "07";
$mes["Agosto"] = "08";
$mes["Septiembre"] = "09";
$mes["Octubre"] = "10";
$mes["Noviembre"] = "11";
$mes["Diciembre"] = "12";

Pues ya acabamos igual que antes:

$dia = $array_fecha[1];
$texto_mes = $array_fecha[3];
$ano = $array_fecha[5];

if ($dia >= 1 && $dia <= 9) { // Si es del 1 al 9 añade un cero delante.
    $dia = "0" . $dia;
}

$fecha_formateada = $ano . "-" . $mes[$texto_mes] . "-" . $dia;

El condicional “if” solo es necesario si en la fecha bonita los nueve primeros días los trae sin el cero, que es lo más lógico. Eso lo hacemos para mantener el formato de dos dígitos. Con esto ya hemos transformado la fecha (Viernes, 23 de Enero de 2015 —-> 2015-01-23), y podremos insertarla en una base de datos, o compararla con otras fechas. El código al completo sería el siguiente:

$array_fecha = explode(" ", $fecha); //Patrón de búsqueda, un espacio en blanco.

$mes["Enero"] = "01";
$mes["Febrero"] = "02";
$mes["Marzo"] = "03";
$mes["Abril"] = "04";
$mes["Mayo"] = "05";
$mes["Junio"] = "06";
$mes["Julio"] = "07";
$mes["Agosto"] = "08";
$mes["Septiembre"] = "09";
$mes["Octubre"] = "10";
$mes["Noviembre"] = "11";
$mes["Diciembre"] = "12";

$dia = $array_fecha[1];
$texto_mes = $array_fecha[3];
$ano = $array_fecha[5];

if ($dia >= 1 && $dia <= 9) { // Si es del 1 al 9 añade un cero delante.
    $dia = "0" . $dia;
}

$fecha_formateada = $ano . "-" . $mes[$texto_mes] . "-" . $dia;

Para comparar fechas es tan fácil como comprobar si una fecha es menor, igual o mayor que la otra. Por ejemplo:

$fecha_bd = "2015-01-05"; // 5 de Enero de 2015.
$fecha_hoy = date("Y-m-d"); // fecha del momento actual (hoy).

if ($fecha_bd < $fecha_hoy) {
    echo "La fecha $fecha_bd de la base de datos es anterior a hoy";
} elseif ($fecha_bd == $fecha_hoy) {
    echo "La fecha $fecha_bd de la base de datos es hoy";
} else {
    echo "La fecha $fecha_bd de la base de datos aún está por llegar";
}

Esto es todo por hoy. En este artículo hemos dado un repaso a una de las muchísimas formas que hay en PHP de formatear fechas y compararlas. Tengo pendiente hacer otro para lo mismo pero en Javascript, ya que muchas veces tenemos que comparar fechas y formatearlas en el lado del cliente. Sí, se pueden subir al servidor las fechas vía Ajax, trabajarlas en PHP y devolverlas al cliente, pero si no es del todo necesario me parece una pérdida de tiempo y recursos, es mucho más eficiente hacerlo en Javascript.

Si has llegado hasta aquí abajo, entiendo que te ha parecido interesante, así que me alegro, por ti, y por mí.

<?php
if ($visitante == "amigo" || $visitante == "amiga") {
    echo "Un abrazo.";
} else {
    echo "Un saludo.";
}
?>
Si te ha gustado, lo puedes compartir.

Deja un comentario

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

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>