VictorJAM.zapto.org
HTML  CSS  Javascript  MySQL  MariaDB 

2024-01-12

Jugando con fechas en php, JavaScript y MySQL.

MySQL

En MySQL el tipo de dato DATETIME se representa como una cadena de texto con la siguiente forma:

"YYYY-MM-DD HH:MM:SS"

YYYY Año completo

MM Mes en número

DD Día en número

HH Hora

MM Minuto

Segundo

Y tenemos varias funciones simples para trabajar con ellas:

NOW() Devuelve la fecha y hora actual.
DATE() Devuelve la parte de la fecha de un dato.
TIME() Devuelve la parte de la hora de un dato.
CURDATE Obtiene la parte "fecha" de la fecha actual.
CURTIME Obtiene la parte "hora" de la fecha actual.

Además con la función EXTRACT podemos extraer la parte que queramos usando su nombre: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.

SELECT EXTRACT(DAY FROM NOW()); ## El día de hoy.

Si queremos buscar un intervalo de fechas podemos usar BETWEEN-AND:

SELECT * FROM tabla WHERE DATE(campofecha) BETWEEN '2023-01-01' AND '2023-02-01';

También podemos "sumar" o "restar" intervalos de tiempo a una fecha usando las funciones DATE_ADD y DATE_SUB siendo su estructura la siguiente:

DATE_ADD(campofecha, INTERVAL valor UNIDAD);

La "UNIDAD" puede ser: MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR, SECOND_MICROSECOND, MINUTE_MICROSECOND, MINUTE_SECOND, HOUR_MICROSECOND, HOUR_SECOND, HOUR_MINUTE, DAY_MICROSECOND, DAY_SECOND, DAY_MINUTE, DAY_HOUR, YEAR_MONTH.

QUARTER representa el año dividido en tres meses. Así Enero-Febrero-Marzo será el primer cuarteto, Abril-Mayo-Junio el segundo, etc. Existe además la función QUARTER() que nos devuelve el número del cuarteto de la fecha pasada como pará

Ejemplos:

select date_sub(curdate(), interval 1 day) -- Le quita un día a la fecha actual.
select date_add(now(), interval "1 2" DAY_HOUR) -- Le añade a la fecha actual 1 día y 2 horas.

Aunque podemos simplificar sin usar las funciones dat¡e_add/ date_sub usando los signos de sumar y restar:

select curdate() - interval 1 day; -- Le quita un día a la fecha actual.
select now() + interval "1 2" DAY_HOUR; --La añade a la fecha actual 1 día y 2 horas.

La diferencias entre dos fechas la podemos hallar con la función DATEDIFF

select datediff("2023-01-01", "2023-12-31"); -- Devolverá -364 dado que la fecha
-- primera es menor que la segunda y devuelve un negativo.

Si bien no nos gusta el "formato" de fecha para mostrar, podemos usar la función DATE_FORMAT() para cambiar los parámetros a otra forma que nos guste:

select date_format(now(), '%d-%m-%Y %H:%i");

Los selectores que nos permiten modificar el formato son los siguientes:

%a Día de la semana abrevia (inglés).
%b Nombre del mes abreviado (inglés).
%c Mes numérico (1-12)
%d Dia del mes numérico (01-31)
%d Dia del mes con sufijo en inglés (st, nd, etc.)
%e Dia del mes numérico (1-31)
%f Microsegundo (000000-999999
%h Hora 01-12
%H Hora (00-23)
%i Minutos (00-59)
%I Hora (01-12)
%j Dia del año (011-366)
%k Hora (0-23)
%l Hora (1-12)
%m Mes numérico (00-12)
%M Nombre del mes en inglés
%p AM o PM
%r Tiempo 12 horas (AM-PM)
%s Segundos 0-59
%S Segundo 00-59
%T Tiempo 24 horas
%u Semana (00-53) siendo el lunes el primer día de la semana
%U Semana (00-53) siendo el domingo el primer día de la semana
%v Semana (01-53) siendo el lunes el primer día de la semana.
%V Semana (01-53) siendo el domingo el primer día de la semana.
%w Dia de la semana 0=Sunday-6=Saturday.
%W Nombre del día ingles.
%x Año numero con 4 dígitos (lunes primer día semana)
%X Año numero con 4 dígitos (domingo primer día de semana
%y Año con dos dígitos
%Y Año con 4 dígitos.
%% El símbolo %

PHP: date() y time()

En php tenemos dos formas de trabajar con fechas. La primera de ellas son con las funciones date() y time().

time() es equivalente a UNIX devolviendo el número de segundos desde el 1 de enero de 1970 a la media noche.

La función date(), sin embargo, devuelve una cadena con el formato que nosotros le pasamos como parámetro.

$d = date("Y m d"); // $d="2023-01-01";

Las opciones principales para dar el formato son:

a am/pm
A AM/PM
d Día del mes 00-31
D Dia de la semana Mon..Sun
g Horas 1-12
G Horas 0-13
h Horas 01-12
H Horas 00-23
i Minutos 00-59
j Días del mes 1 a 31
l Día de la semana sunday-monday
m Mes 01-12
M Mes Jan-Dec
n Mes 1-12
s Segundos 00-59
y Año dos dígitos
Y Años 4 dígitos
Se puede ver una lista completa de estos parámetros en date()

date() acepta un segundo parámetro que será un valor UNIX de tiempo. Si no se especifica directamente se le asigna la hora actual.

Para pasar de cadena a tiempo se usa la función strtotime() pasando como parámetro una cadena previamente formateada. Así usando strtotime() y date() podemos hacer cosas como:

$fecha = "2023-01-01 18:50:00";      // Fecha en formato SQL.
$dia = date("d", strtotime($fecha)); // día
$mes = date("m", strtotime($fecha)); // mes
$ano = date("Y", strtotime($fecha)); // ano
$h   = date("H", strtotime($fecha)); // hora
$m   = date("i", strtotime($fecha)); // minuto
$s   = date("s", strtotime($fecha)); // segundo

Por último cabe mencionar la función getDate que nos devuelve un array asociativo con la fecha. Esta función acepta un parámetro número que será un valor de UNIX si no es pasado se toma la hora actual. Ejemplo:

$x = getDate();
foreach ($x as $k=>$v ) {
  echo '['.$k.']='.$v.';
'; }

Cuyo resultado es:

[seconds]=1;
[minutes]=1;
[hours]=18;
[mday]=10;
[wday]=3;
[mon]=1;
[year]=2024;
[yday]=9;
[weekday]=Wednesday;
[month]=January;
[0]=1704906061;

PHP: DateTime()

La otra forma de trabajar con fechas en php es usando el objeto DateTime. Este objeto es muy potente a la vez que un poco lioso de usar.

Veamos un ejemplo para que se entienda:

// Creamos el objeto usando el operador new.
$date = new DateTime();
// Para poder mostrarlo debemos usar el método format que es muy parecido a
// la función date().
echo $date->format("Y-m-d H:i").'<br>';
// Añadimos un intervalo de 1 hora.
$date->add(DateInterval::CreateFromDateString("1 hour"));
echo $date->format("Y-m-d H:i").'<br>';
// Añadimos un intervalo de un dia
$date->sub(DateInterval::CreateFromDateString("1 days"));
echo $date->format("Y-m-d H:i").'<br>';
// Hacemos lo mismo con el método modify.
$date->modify("-1weeks");
echo $date->format("Y-m-d H:i").'<br>';
echo '<hr>';

$f = new DateTime("2023-03-01");
echo $f->format("Y-m-d H:i:s").'<br>';
date_add($f, date_interval_create_from_date_string("10 days"));
echo $f->format("Y-m-d H:i:s").'<br>';

$datetime1 = date_create('2009-10-11');
$datetime2 = date_create('2009-10-13');
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%R%a días');

JavaScript

En JavaScript tenemos el objeto Date para trabajar con fechas.

Cada vez que intentemos hacer un "log" de una variable de tipo date nos dará como salida:

Thu Jan 11 2024 16:44:00 GMT+0100 (hora estándar de Europa central)
Por defecto, JavaScript mostrará la zona que tenga asignada el navegador.

Hay nueve formas de crear un objeto date:

var f = new Date() ;         // Sin parámetros. Se establece a la hora actual.
var f = new Date('string') ; // Usando una cadena con el formato fecha.

// Usando números, como  partes de la fecha.
var f = new Date(ano, mes) ;
var f = new Date(ano, mes, dia) ;
var f = new Date(ano, mes, dia, hora) ;
var f = new Date(ano, mes, dia, hora, minutos) ;
var f = new Date(ano, mes, dia, hora, minutos, segundos) ;
var f = new Date(ano, mes, dia, hora, minutos, segundos, ms) ;

var f = new Date(t) ; // t cantidad de ms desde la fecha UNIX.

Internamente la información se guarda como una fecha UNIX que podremos obtener con la función getTime().

Los métodos más importantes para obtener un dato son:

getFullYear() Año completo
getMonth Mes.
getDate Día del mes.
getDay Día de la semana.
getHours Hora.
getMinutes Minutos
getSeconds Segundos.
getMillisecons Milisegundos.
getTime Tiempo UNIX

Que tienen su equivalente para establecer el dato cambiando "get" por "set".

Otros métodos mas útiles son: now(), parse() y toISOString() que podemos usar para obtener la fecha actual, analizar un string con una fecha y convertir un objeto date en una cadena de texto.

Una cadena ISO de fecha tiene la forma:

2023-10-14T22:30:00.000Z

Voy a poner un poco de código de como convierto una cadena en un objeto DATE y como puedo volver a hacer el proceso inverso, teniendo en cuenta que hay un problema con las zonas horarias.

var s = "2023-10-14 02:34:00"; // s es una fecha en formato MySQL.

var a = Date.now();    // a será un número con la fecha UNIX.
var b = Date.parse(s); // b será un número con la fecha UNIX con la fecha s.

// Si no queremos usar parse, podemos dividir la cadena usando la función 
// split y una expresión regular.
var partes = s.split(/[- :]/);
partes[1]--; // El mes va de 0 a 11 en el objeto Date.
// Creamos el objeto.
var c = new Date(partes[0], partes[1], partes[2], partes[3], partes[4], partes[5]);

// Si queremos hacer el proceso contrario, es decir, un objeto date convertirlo
// a un string podemos hacer: 
console.log(c.toISOString().replace('T', ' ').replace('Z', ' ').slice(0,19));
// Pero si comprobamos la salida vemos que hemos perdido dos horas, esto se 
// debe al uso de la zona horaria que hace Date. 

// Para solucionar el problema podemos hacer los siguiente:
var c = new Date( s ); // Obtenemos un objeto Date usando el string.
// Obtenemos el offset de la zona horaria del objeto en minutos (x60000 para 
// tener los milisengundos.
var d = c.getTimezoneOffset()*60000; 
// Ahora creamos otro objeto quitando el offset a la fecha.
var e = new Date(Date.parse(s)-d);
// Y ya podemos mostrar correctamente el valor de la fecha con toISOString.
console.log(e.toISOString().replace('T', ' ').replace('Z', ' ').slice(0,19));

Referencias

Baiaxip

OpenWebInars

w3schools (date)