Hora actual en MySQL: NOW(), CURDATE(), UTC_TIMESTAMP(), zonas horarias y buenas prácticas

目次

1. Obtener la hora actual en MySQL (Conclusión: Hoja de trucos SQL más corta)

Si deseas obtener la hora actual en MySQL, solo hay unas pocas funciones SQL que necesitas recordar.
Abajo está la respuesta más corta para la palabra clave de búsqueda “MySQL get current time”.

1.1 Fecha y hora actuales en MySQL: NOW() / CURRENT_TIMESTAMP

Devuelve la fecha + hora actual (YYYY-MM-DD HH:MM:SS).

SELECT NOW();
SELECT CURRENT_TIMESTAMP;

Salida de ejemplo

2025-02-01 15:30:45
  • NOW() y CURRENT_TIMESTAMP usualmente devuelven el mismo resultado.
  • Ambos devuelven la fecha y hora actuales.
  • Si necesitas milisegundos, usa lo siguiente.
    SELECT NOW(3);
    

Notas (errores comunes)

  • Depende de la configuración de zona horaria del servidor.
  • En un entorno UTC, podrías obtener UTC en lugar de la hora de Japón.
  • Durante la ejecución de la consulta, básicamente devuelve la misma hora (fija dentro de una única sentencia).

1.2 Fecha actual en MySQL: CURDATE()

Devuelve solo la fecha (sin hora).

SELECT CURDATE();

Salida de ejemplo

2025-02-01

Casos de uso

  • Consultar los datos de hoy
  • Comparaciones de fechas (p.ej., filtrar solo los registros de hoy)

Notas

  • El valor devuelto es de tipo DATE.
  • No es adecuado cuando necesitas procesar la hora del día.

1.3 Hora actual en MySQL: CURTIME()

Devuelve solo la hora.

SELECT CURTIME();

Salida de ejemplo

15:30:45

Casos de uso

  • Verificaciones de horario comercial
  • Lógica de ramificación por ventana de tiempo

Notas

  • No incluye información de fecha.
  • No puede usarse para comparar con columnas de tipo DATE.

1.4 Hora actual UTC en MySQL: UTC_TIMESTAMP()

Devuelve la hora en UTC (Tiempo Universal Coordinado), sin importar la configuración de zona horaria del servidor.

SELECT UTC_TIMESTAMP();

Salida de ejemplo

2025-02-01 06:30:45

Cuándo deberías usarlo

  • Servicios globales
  • Diseños que almacenan registros en UTC de forma consistente

Errores comunes

  • Mezclarlo con NOW() provoca desfases horarios
  • Si la aplicación asume JST, verás una diferencia de 9 horas

1.5 Hora actual en MySQL con milisegundos: NOW(3) / CURRENT_TIMESTAMP(3)

MySQL 5.6 y posteriores soportan segundos fraccionarios.

SELECT NOW(3);
SELECT CURRENT_TIMESTAMP(3);

Salida de ejemplo

2025-02-01 15:30:45.123

Notas para almacenar

Tu columna también debe soportar segundos fraccionarios.

DATETIME(3)
TIMESTAMP(3)

Si lo almacenas en una columna que no lo soporta, la parte fraccionaria será truncada.

1.6 Hoja de trucos rápida por propósito

PurposeSQL
Current date and timeSELECT NOW();
Get UTCSELECT UTC_TIMESTAMP();
Date onlySELECT CURDATE();
Time onlySELECT CURTIME();
Get millisecondsSELECT NOW(3);

Resumen de trampas comunes

  • La hora está desplazada porque no verificaste la zona horaria
  • Usar NOW(3) sin una columna que admita milisegundos
  • Mezclar UTC y hora local
  • No comprender la diferencia entre DATETIME y TIMESTAMP

MySQL DATETIME と TIMESTAMP の違いを示した図。TIMESTAMPはUTC変換され、DATETIMEは変換されない。

Diferencia entre MySQL DATETIME y TIMESTAMP (comparando si ocurre conversión de zona horaria)

2. Diferencias entre MySQL NOW() y CURRENT_TIMESTAMP

NOW() y CURRENT_TIMESTAMP se ven similares, pero no comprender dónde usarlos y cómo se comportan puede generar fácilmente errores. Aquí organizamos las diferencias, el uso correcto y los errores comunes.

2.1 ¿Cuál deberías usar? (uso en SELECT / uso en DEFAULT)

■ Al obtener la fecha/hora actual en SELECT

SELECT NOW();
SELECT CURRENT_TIMESTAMP;

Normalmente, ambos devuelven el mismo resultado.

  • Son equivalentes (sinónimos)
  • El valor devuelto es equivalente a DATETIME
  • Afectado por la configuración de zona horaria

Conclusión práctica

  • Prioriza la legibilidad → NOW()
  • Prioriza el estilo SQL estándar → CURRENT_TIMESTAMP

■ Al establecer un valor por defecto en una columna

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

El punto clave aquí es:

Para un valor por defecto, es común usar CURRENT_TIMESTAMP.

Algunos entornos también permiten NOW(), pero el comportamiento puede variar según la versión de MySQL y el modo SQL. La opción más segura es CURRENT_TIMESTAMP.

2.2 Uso correcto de DEFAULT / ON UPDATE

Si deseas actualizar automáticamente una marca de tiempo “updated at”:

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP
);

Comportamiento

  • En INSERT → establece la hora actual para created_at / updated_at
  • En UPDATE → actualiza solo updated_at

Errores comunes

  • No coincidir la precisión de fracciones de segundo al usar DATETIME
  • Encontrar limitaciones de versiones antiguas de MySQL con múltiples columnas TIMESTAMP (MySQL 5.6 y anteriores tenían restricciones)

2.3 Diferencias entre NOW() y SYSDATE() (Importante)

El punto fácil de pasar por alto es la diferencia con SYSDATE().

SELECT NOW(), SYSDATE();

■ Diferencias de comportamiento

  • NOW() → fijado al inicio de la consulta
  • SYSDATE() → devuelve la hora en el momento en que se llama

Ejemplo:

SELECT NOW(), SLEEP(3), NOW();

NOW() devuelve el mismo valor.

SELECT SYSDATE(), SLEEP(3), SYSDATE();

SYSDATE() muestra una diferencia de 3 segundos.

2.4 ¿Cuál deberías usar?

FunctionBehaviorRecommended use
NOW()Fixed within a queryLogging, consistency-focused
SYSDATE()Call-time valuePrecise real-time retrieval

Por qué NOW() se recomienda frecuentemente en sistemas reales

  • Mantiene la consistencia dentro de una transacción (un mecanismo que procesa varias sentencias SQL juntas)
  • Más seguro en entornos de replicación

2.5 Malentendidos y problemas comunes

❌ “NOW() y CURRENT_TIMESTAMP son exactamente lo mismo, así que no necesitas pensarlo.”

→ Las diferencias pueden aparecer en valores por defecto o en el comportamiento de actualización, según el entorno.

❌ “SYSDATE() es más preciso, así que siempre es mejor.”

→ Puede causar problemas en entornos de replicación.

❌ No verificar la zona horaria

SHOW VARIABLES LIKE '%time_zone%';

Si lo usas sin comprobar, puedes obtener desfases horarios.

2.6 Buenas prácticas

  • Recuperación con SELECT → NOW()
  • Valor por defecto de columna → CURRENT_TIMESTAMP
  • Auto‑actualización → ON UPDATE CURRENT_TIMESTAMP
  • Enfoque en consistencia → por defecto NOW()
  • Diseño basado en UTC → TIMESTAMP + almacenar en UTC

3. Formateo de la hora actual en MySQL (DATE_FORMAT / TIME_FORMAT)

Después de obtener la hora actual en MySQL, es muy común cambiar el formato de visualización.
Para la intención de búsqueda “formato de hora actual en MySQL”, la función más importante a comprender es DATE_FORMAT().

3.1 Formateo de datetime en MySQL: DATE_FORMAT(NOW(), …)

Sintaxis básica:

sql
SELECT DATE_FORMAT(target_datetime, 'format_string');

Ejemplo: formatear la hora actual

sql
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

Salida de ejemplo

2025-02-01 15:30:45

Especificadores de formato más usados

EspecificadorSignificadoEjemplo
%YAño (4 dígitos)2025
%mMes (2 dígitos)02
%dDía (2 dígitos)01
%HHora (formato 24 h)15
%hHora (formato 12 h)03
%iMinuto30
%sSegundo45
%pAM/PMPM

3.2 Conversión a formato estilo japonés o de 12 h

■ Formato estilo japonés

sql
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');

Salida de ejemplo:

2025-02-01 15:30

■ Formato de 12 h + AM/PM

sql
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %h:%i:%s %p');

Salida de ejemplo:

2025-02-01 03:30:45 PM

3.3 Formateo solo de hora en MySQL: TIME_FORMAT()

Una función de formateo específicamente para datos de tipo TIME.

sql
SELECT TIME_FORMAT(CURTIME(), '%H:%i');

Salida de ejemplo:

15:30

Notas
TIME_FORMAT() es solo para tipo TIME.
– Para DATETIME, use DATE_FORMAT().

3.4 Conversión de cadena → datetime: STR_TO_DATE()

Para convertir datos de cadena a un tipo datetime:

sql
SELECT STR_TO_DATE('2025-02-01 15:30:45', '%Y-%m-%d %H:%i:%s');

Salida de ejemplo:

2025-02-01 15:30:45

Errores comunes
– Incompatibilidad de formato devuelve NULL.
– Confundir %m y %c (mes con ceros vs sin ceros).

3.5 Puntos importantes en producción

❌ No compare después de formatear

Ejemplo incorrecto:

sql
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-01';

Esto no se recomienda porque los índices dejan de ser efectivos (el rendimiento de la consulta se degrada).

Recomendado:

sql
WHERE created_at >= '2025-02-01' AND created_at < '2025-02-02';

❌ No sobre‑formatee en el lado de la base de datos
En aplicaciones web, el formateo para la visualización suele ser más flexible en el lado de la aplicación.
La base de datos debe centrarse en “almacenamiento y cálculo”.

3.6 Formateo con milisegundos

sql
SELECT DATE_FORMAT(NOW(3), '%Y-%m-%d %H:%i:%s.%f');

%f representa microsegundos (6 dígitos).

Nota
Si la columna no es DATETIME(3) o similar, la parte fraccionaria será truncada.
Disponible en MySQL 5.6 y posteriores.

3.7 Resumen por propósito de formateo

PropósitoFunción
Cambiar formato de visualizaciónDATE_FORMAT
Formatear solo la horaTIME_FORMAT
Conversión de cadena → datetimeSTR_TO_DATE
Mostrar milisegundos%f

4. Suma y resta de fechas y horas en MySQL (DATE_ADD / DATE_SUB)

Aunque puedas obtener la hora actual, no puedes usarla eficazmente en producción sin cálculos de fecha/hora como “X días después” o “hace X horas”.
Aquí explicamos cómo usar DATE_ADD() y DATE_SUB() con la hora actual en MySQL.

4.1 Suma de datetime en MySQL: DATE_ADD()

Sintaxis básica:

sql
SELECT DATE_ADD(base_datetime, INTERVAL value unit);

Ejemplo: 7 días a partir de ahora

sql
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);

Ejemplo: 2 horas después

sql
SELECT DATE_ADD(NOW(), INTERVAL 2 HOUR);

Unidades más usadas

UnidadSignificado
SECONDSegundos
MINUTEMinutos
HOURHoras
DAYDías
MONTHMeses
YEARAños

4.2 Resta de datetime en MySQL: DATE_SUB()

Sintaxis básica:

sql
SELECT DATE_SUB(base_datetime, INTERVAL value unit);

Ejemplo: hace 30 días

sql
SELECT DATE_SUB(NOW(), INTERVAL 30 DAY);

Ejemplo: hace 1 hora

sql
SELECT DATE_SUB(NOW(), INTERVAL 1 HOUR);

Casos de uso
– Verificaciones de expiración
– Eliminación de registros antiguos
– Extracción de datos recientes

4.3 Patrones comunes en producción

■ Recuperar datos de las últimas 24 horas

sql
SELECT * FROM logs WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY);

■ Establecer una fecha límite 7 días después

sql
INSERT INTO tasks (deadline) VALUES (DATE_ADD(NOW(), INTERVAL 7 DAY));

4.4 Errores comunes y precauciones
❌ Aplicar funciones a columnas
Ejemplo incorrecto:
WHERE DATE(created_at) = CURDATE();
Esto desactiva los índices (optimización del rendimiento de la consulta).
Recomendado:
WHERE created_at >= CURDATE() AND created_at < DATE_ADD(CURDATE(), INTERVAL 1 DAY);
❌ Ignorar zonas horarias
NOW() se basa en la zona horaria del servidor
Si almacenas en UTC, usa UTC_TIMESTAMP() como base
Ejemplo:
SELECT DATE_ADD(UTC_TIMESTAMP(), INTERVAL 1 DAY);
❌ Problemas al añadir meses
SELECT DATE_ADD('2025-01-31', INTERVAL 1 MONTH);
→ Debido al ajuste de fin de mes, la fecha puede cambiar.
(El resultado puede ser 2025-02-28 dependiendo del entorno.)
Comprende la especificación antes de usar cálculos basados en meses.

4.5 Suma con milisegundos
SELECT DATE_ADD(NOW(3), INTERVAL 500 MILLISECOND);
※ MySQL no soporta MILLISECOND directamente.
Especifica en microsegundos:
SELECT DATE_ADD(NOW(3), INTERVAL 500000 MICROSECOND);

4.6 Mejores prácticas
Estandariza NOW() o UTC_TIMESTAMP() como base
No apliques funciones a columnas en la cláusula WHERE
Comprende el comportamiento de la suma basada en meses
Si se requiere precisión, usa DATETIME(3) o superior

5. Calcular diferencias de fecha/hora en MySQL (DATEDIFF / TIMESTAMPDIFF)

En sistemas de producción, simplemente obtener la hora actual no es suficiente. A menudo necesitas calcular cuántos días han pasado o cuántas horas quedan.

5.1 Calcular diferencias de fechas: DATEDIFF()

DATEDIFF() calcula la diferencia en días entre dos fechas.

SELECT DATEDIFF('2025-02-10', '2025-02-01');

Resultado

9

Puntos clave

  • Devuelve la diferencia solo en días
  • La parte de tiempo se ignora
  • El resultado puede ser negativo

Ejemplo: calcular días desde la creación

SELECT DATEDIFF(NOW(), created_at)
FROM users;

5.2 Calcular diferencias por unidad: TIMESTAMPDIFF()

TIMESTAMPDIFF() permite especificar la unidad.

SELECT TIMESTAMPDIFF(unit, start_datetime, end_datetime);

Ejemplo: diferencia en horas

SELECT TIMESTAMPDIFF(HOUR, '2025-02-01 10:00:00', '2025-02-01 15:00:00');

Resultado

5

Unidades comunes

UnitMeaning
SECONDSeconds
MINUTEMinutes
HOURHours
DAYDays
MONTHMonths
YEARYears

Ejemplo: calcular minutos desde el inicio de sesión

SELECT TIMESTAMPDIFF(MINUTE, login_at, NOW())
FROM users;

5.3 Casos de uso en producción

  • Verificaciones de tiempo de expiración de sesión
  • Verificaciones de expiración de suscripción
  • Calcular tiempo transcurrido en registros
  • Lógica de limitación de velocidad

5.4 Errores comunes

❌ Usar DATEDIFF cuando se requiere precisión de tiempo

DATEDIFF() ignora horas y minutos.

❌ Invertir el orden de los argumentos

El orden es:

TIMESTAMPDIFF(unit, start, end)

Si se invierte, el resultado se vuelve negativo.

❌ Ignorar zonas horarias

Si se mezclan UTC y hora local, las diferencias pueden ser incorrectas.

5.5 Mejores prácticas

  • Usa TIMESTAMPDIFF() cuando la precisión de tiempo es importante
  • Usa DATEDIFF() para cálculos simples de días
  • Asegura un uso consistente de la zona horaria
  • Estandariza en UTC en sistemas distribuidos

6. Consultas de rango de fechas usando la hora actual

Uno de los requisitos reales más comunes es obtener registros dentro de un rango de tiempo específico, como:

  • Registros de hoy
  • Últimos 7 días
  • Últimas 24 horas
  • Este mes

6.1 Obtener los registros de hoy (amigable con índices)

SELECT *
FROM logs
WHERE created_at >= CURDATE()
  AND created_at < DATE_ADD(CURDATE(), INTERVAL 1 DAY);

Por qué esto es correcto

  • No se aplica ninguna función a la columna
  • Los índices siguen utilizables
  • Consulta de rango eficiente

6.2 Últimos 7 días

SELECT *
FROM logs
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);

6.3 Últimas 24 horas

SELECT *
FROM logs
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY);

6.4 Este mes

SELECT *
FROM logs
WHERE created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')
  AND created_at < DATE_ADD(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH);

En los sistemas de producción, a menudo es mejor calcular los límites en el lado de la aplicación y pasarlos como parámetros.

6.5 Errores comunes de rendimiento

❌ Aplicar funciones a columnas indexadas

WHERE DATE(created_at) = CURDATE();

Esto impide el uso del índice y provoca escaneos completos de la tabla.

❌ Usar BETWEEN sin cuidado

BETWEEN es inclusivo y puede causar problemas de desfase de un segundo.

6.6 Resumen de buenas prácticas

  • Siempre use condiciones de rango para el filtrado de fechas
  • Evite aplicar funciones a columnas indexadas
  • Prefiera el almacenamiento en UTC en sistemas globales
  • Sea explícito sobre las suposiciones de zona horaria