Trabajar con fechas es una tarea que al estar sujeta a tantas reglas especiales (meses con distinta cantidad de días, años bisiestos, comienzo de mes a media semana, etc) puede ser muy compleja si lo intentamos abordar sin el apoyo de una buena base.
Anteriormente he escrito sobre cómo trabajar con fechas en PHP y en Javascript: en ambos casos contamos con el concepto de fechas como objetos, lo que ordena y facilita bastante su manipulación a través de los métodos propios de cada lenguaje.
En MySQL existe a su vez un concepto de fechas y tiempos como tipos de datos con sus propias características, y junto con ellos, un montón de funciones que nos pueden servir para realizar distintos cálculos y operaciones al realizar consultas.
Tipos de fecha y horas
En MySQL existen los siguientes tipos de fecha y tiempo:
DATETIME
corresponde a una representación completa de fecha y hora, es decir, algo como el 25 de octubre del 2014 a las 8:00 pm, lo que se almacena del modo2014-10-25 20:00:00
. Es notable la ausencia de la indicación de una zona horaria, cuya gestión queda delegada a la aplicación.- Los tipos
DATE
yTIME
, como quizás ya estás adivinando, almacenan solamente fecha o solamente hora. Los formatos son los mismos que su parte correspondiente en una columnaDATETIME
, es decir,YYYY-MM-DD
para las fechas yHH:MM:SS
para el tiempo. - El tipo
YEAR
es un dato aun más específico y almacena solamente un año. Aunque se puede almacenar sólo con 2 dígitos, creo que no es necesario ahondar en lo evidentemente necesario de utilizar el formato de 4 dígitos. - Finalmente, existe el tipo
TIMESTAMP
que es similar a DATETIME pero con la salvedad de que todos los datos son convertidos hacia y desde UTC al escribir y leer la información, tomando como base la configuración de zona horaria del servidor, o bien, si se ha especificado, de la conexión con el motor de base de datos. Por ejemplo, si mi servidor está en la zona horaria de Santiago de Chile y voy a guardar el dato2014-01-30 12:00:00
, MySQL lo convierte a2014-01-30 15:00:00
que sería la fecha y hora correspondientes en UTC.
Utilizando fechas y horas en consultas
Como ya sabemos que MySQL “entiende” de fechas y horas, podemos hacer consultas relacionadas con éstas de forma muy sencilla. Por ejemplo, si queremos averiguar las entradas de WordPress publicadas en una jornada de trabajo en particular:
SELECT * FROM wp_posts WHERE post_date >= '2014-03-19 08:00:00' AND post_date <= '2014-03-19 18:00:00' AND post_status = 'publish' ORDER BY post_date ASC
… donde post_date
es una columna con datos tipo DATETIME
.
También podríamos consultar por todas las entradas publicadas un día en particular, sin importar la hora. Para esto, una opción ingenua sería:
SELECT * FROM wp_posts WHERE post_date >= '2014-03-19 00:00:00' AND post_date <= '2014-03-19 23:59:59' AND post_status = 'publish' ORDER BY post_date ASC
Pero también podemos tratar esa columna como si tuviera solamente información de fecha utilizando la función CAST
de MySQL:
SELECT * FROM wp_posts WHERE CAST(post_date AS DATE) = '2014-03-19' AND post_status = 'publish' ORDER BY post_date ASC
Además podemos extraer parte de la fecha, por ejemplo:
SELECT * FROM wp_posts WHERE YEAR( post_date ) = '2014' AND MONTH( post_date ) = '03' AND post_status = 'publish' ORDER BY post_date ASC
Utilizar periodos de tiempo en consultas
También podemos hacer consultas considerando periodos de tiempo; lo que es especialmente útil cuando queremos saber, por ejemplo, las entradas publicadas en un mes en particular. En lugar de tratar de adivinar cuántos días tiene el mes por el que estamos consultando, podemos definir un rango de forma más sencilla; por ejemplo, podemos formular la misma consulta anterior de este modo:
SELECT * FROM wp_posts WHERE CAST(post_date AS DATE) >= '2014-03-01' AND post_date < DATE_ADD( '2014-03-01', INTERVAL 1 MONTH ) AND post_status = 'publish' ORDER BY post_date ASC