La función TIME_FORMAT() convierte un valor de tipo TIME en una cadena de texto con el formato que especifiques. Funciona de manera similar a DATE_FORMAT(), pero está diseñada exclusivamente para valores temporales y solo acepta los especificadores relacionados con horas, minutos y segundos. Los especificadores de fecha como %Y, %m o %d producen NULL o valores vacíos cuando se usan con TIME_FORMAT().

Esta función es la herramienta adecuada cuando necesitas presentar horas en formatos legibles, como convertir 14:32:08 a 2:32 PM, mostrar duraciones en un formato amigable o adaptar la representación horaria a las convenciones locales de presentación.

Sintaxis

TIME_FORMAT(hora, formato)

El primer argumento es un valor de tipo TIME, un DATETIME (del cual se usará solo la parte horaria) o una cadena que MySQL pueda interpretar como hora. El segundo argumento es la cadena de formato con especificadores precedidos por %.

Los especificadores válidos para TIME_FORMAT() son los mismos que los especificadores de hora de DATE_FORMAT():

EspecificadorDescripciónEjemplo
%HHora 24h con cero inicial (00-23)14
%kHora 24h sin cero inicial (0-23)14
%h o %IHora 12h con cero inicial (01-12)02
%lHora 12h sin cero inicial (1-12)2
%iMinutos con cero inicial (00-59)32
%s o %SSegundos con cero inicial (00-59)08
%fMicrosegundos (000000-999999)451293
%pIndicador AM/PMPM
%rHora completa en formato 12h02:32:08 PM
%THora completa en formato 24h14:32:08

Comportamiento básico

La operación más común de TIME_FORMAT() es convertir entre formato de 24 horas y formato de 12 horas con indicador AM/PM.

SELECT TIME_FORMAT('14:32:08', '%h:%i:%s %p') AS formato_12h;
formato_12h
02:32:08 PM

El proceso inverso, mostrar una hora en formato de 24 horas con el formato compuesto %T, es igualmente directo.

SELECT TIME_FORMAT('02:32:08', '%T') AS formato_24h;
formato_24h
02:32:08

Puedes simplificar la salida omitiendo los segundos cuando no son relevantes.

SELECT TIME_FORMAT('14:32:08', '%H:%i') AS sin_segundos_24h,
       TIME_FORMAT('14:32:08', '%h:%i %p') AS sin_segundos_12h;
sin_segundos_24hsin_segundos_12h
14:3202:32 PM

La opción %l muestra la hora en formato de 12 horas sin el cero inicial, lo que resulta más natural para lectura humana.

SELECT TIME_FORMAT('09:05:00', '%h:%i %p') AS con_cero,
       TIME_FORMAT('09:05:00', '%l:%i %p') AS sin_cero;
con_cerosin_cero
09:05 AM9:05 AM

También puedes incluir texto literal en la cadena de formato.

SELECT TIME_FORMAT('14:32:08', '%H horas, %i minutos y %s segundos') AS descriptivo;
descriptivo
14 horas, 32 minutos y 08 segundos

Caso práctico: presentar horarios de atención

Imagina que tienes una tabla con los horarios de atención de las sucursales de un negocio y necesitas mostrarlos en un formato amigable para los clientes.

CREATE TABLE sucursales (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(100) NOT NULL,
    hora_apertura TIME NOT NULL,
    hora_cierre TIME NOT NULL,
    ciudad VARCHAR(50) NOT NULL
);
 
SELECT nombre, ciudad,
       CONCAT(
           TIME_FORMAT(hora_apertura, '%l:%i %p'),
           ' - ',
           TIME_FORMAT(hora_cierre, '%l:%i %p')
       ) AS horario
FROM sucursales
ORDER BY ciudad, nombre;
nombreciudadhorario
Centro ComercialGuadalajara10:00 AM - 9:00 PM
Plaza UniversidadGuadalajara9:00 AM - 8:00 PM
Sucursal CentroMéxico DF8:30 AM - 6:30 PM
Sucursal PolancoMéxico DF9:00 AM - 8:00 PM
Sucursal ValleMonterrey8:00 AM - 7:00 PM

Este formato es mucho más legible para los clientes que mostrar 08:30:00 - 18:30:00.

Para calcular y mostrar la duración del horario de atención en formato legible, combina TIMEDIFF con TIME_FORMAT().

SELECT nombre,
       TIME_FORMAT(hora_apertura, '%l:%i %p') AS abre,
       TIME_FORMAT(hora_cierre, '%l:%i %p') AS cierra,
       TIME_FORMAT(TIMEDIFF(hora_cierre, hora_apertura), '%H:%i') AS horas_servicio
FROM sucursales;
nombreabrecierrahoras_servicio
Sucursal Centro8:30 AM6:30 PM10:00
Sucursal Polanco9:00 AM8:00 PM11:00
Centro Comercial10:00 AM9:00 PM11:00
Plaza Universidad9:00 AM8:00 PM11:00
Sucursal Valle8:00 AM7:00 PM11:00

Caso práctico: formatear registros de asistencia

En un sistema de control de asistencia, los empleados ven sus horas de entrada y salida. Presentar estas horas en formato de 12 horas con AM/PM es más intuitivo que el formato militar de 24 horas.

SELECT e.nombre,
       TIME_FORMAT(ra.hora_entrada, '%h:%i %p') AS entrada,
       TIME_FORMAT(ra.hora_salida, '%h:%i %p') AS salida,
       TIME_FORMAT(
           TIMEDIFF(ra.hora_salida, ra.hora_entrada),
           '%H h %i min'
       ) AS trabajado
FROM registros_asistencia ra
JOIN empleados e ON e.id = ra.empleado_id
WHERE ra.fecha = '2025-07-15'
  AND ra.hora_salida IS NOT NULL;
nombreentradasalidatrabajado
Carlos Ruiz08:47 AM05:30 PM08 h 42 min
Ana Martínez09:03 AM05:15 PM08 h 12 min
Pedro Sánchez09:22 AM06:00 PM08 h 37 min

El formato '%H h %i min' produce una representación de duración clara y legible. Ten en cuenta que %H en este contexto muestra las horas totales de la diferencia, no una hora del reloj, ya que el valor proviene de TIMEDIFF.

Caso práctico: comparar formato 12h y 24h en reportes

A veces necesitas mostrar ambos formatos lado a lado, por ejemplo, en un sistema que atiende regiones con diferentes convenciones horarias.

SELECT p.id,
       TIME_FORMAT(TIME(p.fecha_pedido), '%T') AS hora_24h,
       TIME_FORMAT(TIME(p.fecha_pedido), '%r') AS hora_12h,
       TIME_FORMAT(TIME(p.fecha_pedido), '%h:%i %p') AS hora_corta
FROM pedidos p
WHERE p.fecha_pedido >= '2025-07-14'
ORDER BY p.fecha_pedido;
idhora_24hhora_12hhora_corta
8509:15:2209:15:22 AM09:15 AM
8614:32:0802:32:08 PM02:32 PM
8714:32:0802:32:08 PM02:32 PM

El especificador %r es un atajo para %h:%i:%s %p, mientras que %T equivale a %H:%i:%s. Ambos ahorran la escritura de los especificadores individuales cuando necesitas la hora completa.

Las horas de medianoche y mediodía merecen atención especial en formato de 12 horas.

SELECT TIME_FORMAT('00:00:00', '%h:%i %p') AS medianoche,
       TIME_FORMAT('12:00:00', '%h:%i %p') AS mediodia,
       TIME_FORMAT('00:30:00', '%h:%i %p') AS madrugada;
medianochemediodiamadrugada
12:00 AM12:00 PM12:30 AM

Medianoche se representa como 12:00 AM y mediodía como 12:00 PM, siguiendo la convención estándar del formato de 12 horas.

Manejo de NULL

Si cualquiera de los dos argumentos es NULL, TIME_FORMAT() devuelve NULL.

SELECT TIME_FORMAT(NULL, '%H:%i') AS hora_nula,
       TIME_FORMAT('14:32:08', NULL) AS formato_nulo;
hora_nulaformato_nulo
NULLNULL

Al trabajar con columnas que pueden contener valores nulos, proporciona un texto alternativo con COALESCE.

SELECT e.nombre,
       TIME_FORMAT(ra.hora_entrada, '%h:%i %p') AS entrada,
       COALESCE(
           TIME_FORMAT(ra.hora_salida, '%h:%i %p'),
           'En oficina'
       ) AS salida
FROM registros_asistencia ra
JOIN empleados e ON e.id = ra.empleado_id
WHERE ra.fecha = CURDATE();
nombreentradasalida
Carlos Ruiz08:47 AM05:30 PM
Ana Martínez09:03 AMEn oficina

Combinación con otras funciones

TIME_FORMAT() se integra naturalmente con las funciones de extracción y cálculo temporal.

SELECT TIME_FORMAT(CURTIME(), '%h:%i %p') AS hora_actual,
       TIME_FORMAT(ADDTIME(CURTIME(), '02:00:00'), '%h:%i %p') AS en_dos_horas,
       TIME_FORMAT(SUBTIME(CURTIME(), '03:30:00'), '%h:%i %p') AS hace_tres_y_media,
       TIME_FORMAT(SEC_TO_TIME(3661), '%H h %i min %s seg') AS desde_segundos;
hora_actualen_dos_horashace_tres_y_mediadesde_segundos
02:32 PM04:32 PM11:02 AM01 h 01 min 01 seg

La función SEC_TO_TIME convierte un número de segundos en un valor TIME, que luego TIME_FORMAT() puede presentar en cualquier formato deseado. Esta combinación es útil para mostrar duraciones calculadas a partir de segundos totales.

Para extraer la hora de un DATETIME y formatearla directamente, puedes pasar el DATETIME completo a TIME_FORMAT(), que ignorará la parte de fecha automáticamente.

SELECT fecha_pedido,
       TIME_FORMAT(fecha_pedido, '%h:%i %p') AS hora_formateada
FROM pedidos
WHERE id = 86;
fecha_pedidohora_formateada
2025-07-15 14:32:0802:32 PM

Aunque TIME_FORMAT() acepta un DATETIME como entrada, conceptualmente es más claro usar DATE_FORMAT() cuando trabajas con valores DATETIME, reservando TIME_FORMAT() para columnas que almacenan exclusivamente horas o para resultados de funciones que devuelven TIME, como TIMEDIFF() o SEC_TO_TIME().

En el siguiente artículo veremos DATE_ADD para sumar intervalos a una fecha.

Escrito por Eduardo Lázaro