UTC_DATE
La función UTC_DATE devuelve la fecha actual según el estándar UTC (Tiempo Universal Coordinado), sin importar la zona horaria configurada en el servidor o la sesión de MySQL. Mientras que CURDATE devuelve la fecha basada en la zona horaria de la sesión, UTC_DATE siempre refleja la fecha en el meridiano de Greenwich, lo que la convierte en una herramienta fundamental para aplicaciones que operan en múltiples países o regiones.
UTC es el estándar internacional de referencia horaria. A diferencia de las zonas horarias locales, UTC no cambia con el horario de verano ni varía según la ubicación geográfica. Cuando almacenas fechas en UTC, garantizas que todos los registros son comparables entre sí sin ambigüedad, independientemente de dónde se encuentre el usuario que los consulta.
Sintaxis
UTC_DATE
UTC_DATE()La función no recibe argumentos. Puedes invocarla con o sin paréntesis y el resultado es idéntico. Devuelve un valor de tipo DATE en formato YYYY-MM-DD cuando se usa en un contexto de cadena, o como número YYYYMMDD cuando se usa en un contexto numérico.
Comportamiento básico
La forma más directa de usar UTC_DATE es en una consulta SELECT simple para conocer la fecha UTC actual.
SELECT UTC_DATE() AS fecha_utc, CURDATE() AS fecha_local;| fecha_utc | fecha_local |
|---|---|
| 2026-02-14 | 2026-02-14 |
Si tu servidor está configurado en una zona horaria como America/Mexico_City (UTC-6) y ejecutas esta consulta a las 11:30 PM hora local, verás una diferencia notable.
SET time_zone = 'America/Mexico_City';
SELECT UTC_DATE() AS fecha_utc, CURDATE() AS fecha_local;| fecha_utc | fecha_local |
|---|---|
| 2026-02-15 | 2026-02-14 |
En este caso, mientras en Ciudad de México todavía es 14 de febrero, en UTC ya es 15 de febrero. Esta diferencia puede ser crítica para registros contables, auditorías y cualquier sistema donde la fecha exacta importa.
Contexto numérico
Cuando UTC_DATE se utiliza en operaciones aritméticas, MySQL la convierte automáticamente al formato numérico.
SELECT UTC_DATE() + 0 AS fecha_numerica;| fecha_numerica |
|---|
| 20260214 |
Este comportamiento es útil para comparaciones rápidas o para generar identificadores basados en la fecha.
SELECT CONCAT('RPT-', UTC_DATE() + 0) AS codigo_reporte;| codigo_reporte |
|---|
| RPT-20260214 |
Caso práctico: registro de eventos globales
Considera una plataforma de comercio electrónico que opera en varios países. Cada pedido debe registrar la fecha en UTC para que los reportes financieros sean consistentes, sin importar desde qué país se realizó la compra.
CREATE TABLE pedidos (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT NOT NULL,
total DECIMAL(10,2) NOT NULL,
fecha_utc DATE DEFAULT (UTC_DATE()),
created_at DATETIME DEFAULT (UTC_TIMESTAMP())
);
INSERT INTO pedidos (cliente_id, total)
VALUES (1042, 259.90), (2087, 1450.00), (553, 89.50);
SELECT id, cliente_id, total, fecha_utc
FROM pedidos;| id | cliente_id | total | fecha_utc |
|---|---|---|---|
| 1 | 1042 | 259.90 | 2026-02-14 |
| 2 | 2087 | 1450.00 | 2026-02-14 |
| 3 | 553 | 89.50 | 2026-02-14 |
Al usar UTC_DATE() como valor por defecto en la columna, cada registro se marca automáticamente con la fecha UTC del momento de inserción, eliminando la dependencia de la configuración del servidor.
Caso práctico: comparar actividad entre zonas horarias
Un sistema de soporte técnico con agentes en Madrid, Buenos Aires y Bogotá necesita generar un reporte diario basado en la fecha UTC para evitar que los tickets se cuenten doble o se omitan al cruzar medianoche en diferentes zonas.
SELECT
t.id,
t.asunto,
t.fecha_creacion_utc,
a.nombre AS agente,
a.zona_horaria
FROM tickets t
JOIN agentes a ON t.agente_id = a.id
WHERE t.fecha_creacion_utc = UTC_DATE()
ORDER BY t.fecha_creacion_utc;| id | asunto | fecha_creacion_utc | agente | zona_horaria |
|---|---|---|---|---|
| 891 | Error en facturación | 2026-02-14 | Ana Martínez | Europe/Madrid |
| 892 | Problema con envío | 2026-02-14 | Carlos Ruiz | America/Bogota |
| 893 | Solicitud de reembolso | 2026-02-14 | Laura Gómez | America/Argentina/Buenos_Aires |
De esta forma, el reporte del día siempre incluye exactamente 24 horas de actividad sin solapamientos ni huecos.
Caso práctico: vencimiento de promociones
Para una tienda online que lanza promociones con fecha de vencimiento global, usar UTC_DATE asegura que la promoción expire al mismo momento para todos los usuarios, sin importar su ubicación.
SELECT
codigo,
descripcion,
descuento_porcentaje,
fecha_inicio_utc,
fecha_fin_utc,
CASE
WHEN UTC_DATE() < fecha_inicio_utc THEN 'Próximamente'
WHEN UTC_DATE() BETWEEN fecha_inicio_utc AND fecha_fin_utc THEN 'Activa'
ELSE 'Expirada'
END AS estado
FROM promociones
ORDER BY fecha_inicio_utc;| codigo | descripcion | descuento_porcentaje | fecha_inicio_utc | fecha_fin_utc | estado |
|---|---|---|---|---|---|
| WINTER25 | Rebajas de invierno | 25 | 2026-01-15 | 2026-02-10 | Expirada |
| VALENTIN15 | San Valentín | 15 | 2026-02-10 | 2026-02-15 | Activa |
| SPRING20 | Primavera 2026 | 20 | 2026-03-01 | 2026-03-31 | Próximamente |
Manejo de NULL
UTC_DATE nunca devuelve NULL por sí misma, ya que simplemente consulta el reloj del sistema. Sin embargo, al combinarla con columnas que pueden contener valores nulos, debes tener precaución.
SELECT
nombre,
fecha_nacimiento,
DATEDIFF(UTC_DATE(), fecha_nacimiento) / 365.25 AS edad_aproximada
FROM clientes
WHERE fecha_nacimiento IS NOT NULL
LIMIT 3;| nombre | fecha_nacimiento | edad_aproximada |
|---|---|---|
| María García | 1990-06-15 | 35.67 |
| Carlos López | 1985-11-22 | 40.23 |
| Laura Sánchez | 1998-03-08 | 27.94 |
Si fecha_nacimiento fuese NULL, la expresión DATEDIFF devolvería NULL. Por ello el filtro WHERE fecha_nacimiento IS NOT NULL es importante para evitar resultados inesperados.
Combinación con otras funciones
UTC_DATE se complementa con muchas funciones de fecha. Puedes usarla con DATE_ADD para calcular fechas futuras en UTC, o con DATEDIFF para medir intervalos desde una referencia universal.
SELECT
UTC_DATE() AS hoy_utc,
DATE_ADD(UTC_DATE(), INTERVAL 30 DAY) AS en_30_dias_utc,
DATE_ADD(UTC_DATE(), INTERVAL 1 YEAR) AS proximo_anio_utc;| hoy_utc | en_30_dias_utc | proximo_anio_utc |
|---|---|---|
| 2026-02-14 | 2026-03-16 | 2027-02-14 |
También resulta útil combinarla con DAYNAME o DAYOFWEEK para determinar el día de la semana en UTC.
SELECT
UTC_DATE() AS fecha_utc,
DAYNAME(UTC_DATE()) AS dia_semana_utc,
WEEK(UTC_DATE()) AS semana_del_anio;| fecha_utc | dia_semana_utc | semana_del_anio |
|---|---|---|
| 2026-02-14 | Saturday | 6 |
Recuerda que DAYNAME devuelve el nombre en inglés a menos que cambies la variable lc_time_names de la sesión.
En el siguiente artículo veremos UTC_TIME para obtener la hora actual en UTC.
Escrito por Eduardo Lázaro
