STR_TO_DATE
La función STR_TO_DATE convierte una cadena de texto en un valor de fecha o datetime, usando un formato que tú defines. Es la operación inversa de DATE_FORMAT: mientras DATE_FORMAT toma una fecha y la convierte en texto con un formato específico, STR_TO_DATE toma un texto con un formato conocido y lo convierte en una fecha que MySQL puede manipular.
Esta función es una de las más importantes cuando trabajas con datos del mundo real. Los sistemas externos, archivos CSV, APIs legacy y hojas de cálculo rara vez envían las fechas en el formato estándar de MySQL (YYYY-MM-DD). Te encontrarás con formatos como "15/06/2025", "June 15, 2025", "15-jun-2025" y muchas otras variaciones. STR_TO_DATE es tu herramienta para convertir todos estos formatos dispares en fechas reales de MySQL.
Sintaxis
STR_TO_DATE(cadena, formato)El primer argumento es la cadena de texto que contiene la fecha. El segundo es una cadena de formato que describe la estructura de esa cadena, usando los mismos especificadores que DATE_FORMAT. Los especificadores más comunes son:
%Y- Año de 4 dígitos (2025)%y- Año de 2 dígitos (25)%m- Mes numérico con cero inicial (01-12)%c- Mes numérico sin cero inicial (1-12)%d- Día con cero inicial (01-31)%e- Día sin cero inicial (1-31)%H- Hora 24h con cero inicial (00-23)%h- Hora 12h con cero inicial (01-12)%i- Minutos (00-59)%s- Segundos (00-59)%p- AM o PM%M- Nombre del mes en inglés (January, February...)%b- Nombre abreviado del mes (Jan, Feb...)%W- Nombre del día en inglés (Monday, Tuesday...)
La función devuelve un valor DATE si el formato solo contiene componentes de fecha, TIME si solo contiene componentes de hora, o DATETIME si contiene ambos.
Comportamiento básico
El caso más simple es convertir una fecha en formato europeo (día/mes/año) al formato de MySQL:
SELECT
STR_TO_DATE('15/06/2025', '%d/%m/%Y') AS formato_europeo,
STR_TO_DATE('06-15-2025', '%m-%d-%Y') AS formato_americano,
STR_TO_DATE('2025.06.15', '%Y.%m.%d') AS formato_puntos;| formato_europeo | formato_americano | formato_puntos |
|---|---|---|
| 2025-06-15 | 2025-06-15 | 2025-06-15 |
Los tres formatos de entrada son diferentes, pero el resultado es el mismo: una fecha MySQL estándar. Lo importante es que la cadena de formato coincida exactamente con la estructura del texto de entrada: los separadores (/, -, .), el orden de los componentes y la cantidad de dígitos deben corresponderse.
Incluir hora
Cuando el texto incluye hora, el resultado es un DATETIME:
SELECT
STR_TO_DATE('15/06/2025 14:30:00', '%d/%m/%Y %H:%i:%s') AS con_hora,
STR_TO_DATE('15/06/2025 02:30 PM', '%d/%m/%Y %h:%i %p') AS con_ampm;| con_hora | con_ampm |
|---|---|
| 2025-06-15 14:30:00 | 2025-06-15 14:30:00 |
Observa que %H se usa para horas en formato 24h, mientras que %h con %p se usa para horas en formato 12h con AM/PM. Ambas consultas producen el mismo resultado porque las 2:30 PM son las 14:30 en formato 24h.
Caso práctico: importar datos con formato europeo
El escenario más habitual para STR_TO_DATE es importar datos de sistemas que usan formatos de fecha regionales. En muchos países de Europa y Latinoamérica, el formato es día/mes/año, pero MySQL espera año-mes-día:
SELECT
cliente,
fecha_texto,
STR_TO_DATE(fecha_texto, '%d/%m/%Y') AS fecha_mysql,
DATEDIFF(CURDATE(), STR_TO_DATE(fecha_texto, '%d/%m/%Y')) AS dias_desde
FROM (
SELECT 'Ana López' AS cliente, '15/01/2025' AS fecha_texto
UNION SELECT 'Carlos Ruiz', '28/02/2025'
UNION SELECT 'María García', '03/06/2025'
UNION SELECT 'Pedro Sánchez', '31/12/2024'
) importacion;| cliente | fecha_texto | fecha_mysql | dias_desde |
|---|---|---|---|
| Ana López | 15/01/2025 | 2025-01-15 | 154 |
| Carlos Ruiz | 28/02/2025 | 2025-02-28 | 110 |
| María García | 03/06/2025 | 2025-06-03 | 15 |
| Pedro Sánchez | 31/12/2024 | 2024-12-31 | 169 |
Una vez convertidas, las fechas se pueden usar con cualquier función de MySQL: DATEDIFF, DATE_ADD, YEAR, MONTH, etc. Sin la conversión, MySQL trataría "15/01/2025" como una cadena de texto sin significado temporal.
Caso práctico: limpiar formatos mixtos
En la vida real, los datos importados a menudo tienen formatos inconsistentes. Puedes usar CASE junto con STR_TO_DATE para manejar múltiples formatos en la misma consulta:
SELECT
fecha_raw,
CASE
WHEN fecha_raw LIKE '__/__/____' THEN STR_TO_DATE(fecha_raw, '%d/%m/%Y')
WHEN fecha_raw LIKE '____-__-__' THEN STR_TO_DATE(fecha_raw, '%Y-%m-%d')
WHEN fecha_raw LIKE '% __, ____' THEN STR_TO_DATE(fecha_raw, '%M %d, %Y')
ELSE NULL
END AS fecha_limpia
FROM (
SELECT '15/06/2025' AS fecha_raw
UNION SELECT '2025-06-15'
UNION SELECT 'June 15, 2025'
UNION SELECT 'formato_raro'
) datos;| fecha_raw | fecha_limpia |
|---|---|
| 15/06/2025 | 2025-06-15 |
| 2025-06-15 | 2025-06-15 |
| June 15, 2025 | 2025-06-15 |
| formato_raro | NULL |
El patrón LIKE detecta la estructura del texto (dos dígitos, barra, dos dígitos, barra, cuatro dígitos) y aplica el formato de conversión correspondiente. Las cadenas que no coinciden con ningún formato conocido reciben NULL, lo que permite identificar y corregir datos problemáticos posteriormente.
Caso práctico: actualizar una columna de texto a fecha
Un uso muy práctico de STR_TO_DATE es migrar columnas que almacenan fechas como texto a columnas de tipo fecha real. Este es un proceso de dos pasos:
-- Paso 1: verificar la conversión antes de modificar datos
SELECT
id,
fecha_texto,
STR_TO_DATE(fecha_texto, '%d-%m-%Y') AS fecha_convertida
FROM pedidos_importados
WHERE STR_TO_DATE(fecha_texto, '%d-%m-%Y') IS NULL
AND fecha_texto IS NOT NULL;Esta consulta identifica las filas donde la conversión falla (devuelve NULL pero el texto original no es nulo), lo que indica un formato inesperado que necesita atención manual.
-- Paso 2: actualizar la columna real
UPDATE pedidos_importados
SET fecha_pedido = STR_TO_DATE(fecha_texto, '%d-%m-%Y')
WHERE fecha_texto IS NOT NULL
AND STR_TO_DATE(fecha_texto, '%d-%m-%Y') IS NOT NULL;Siempre es buena práctica verificar la conversión antes de ejecutar el UPDATE, para evitar perder datos por formatos que no coinciden.
Caso práctico: parsear fechas con nombres de mes
STR_TO_DATE puede interpretar nombres de meses en inglés, tanto completos como abreviados:
SELECT
STR_TO_DATE('January 15, 2025', '%M %d, %Y') AS mes_completo,
STR_TO_DATE('15-Jan-2025', '%d-%b-%Y') AS mes_abreviado,
STR_TO_DATE('Mar 2025', '%b %Y') AS solo_mes_anio;| mes_completo | mes_abreviado | solo_mes_anio |
|---|---|---|
| 2025-01-15 | 2025-01-15 | 2025-03-00 |
Observa el último caso: cuando solo proporcionas mes y año sin día, MySQL asigna el día 0. Esto puede causar problemas si necesitas una fecha válida, así que en esos casos conviene usar CONCAT o STR_TO_DATE con un día por defecto:
SELECT STR_TO_DATE(CONCAT('01 ', 'Mar 2025'), '%d %b %Y') AS con_dia_default;| con_dia_default |
|---|
| 2025-03-01 |
Es importante saber que %M y %b solo reconocen nombres de meses en inglés. Para meses en español (enero, febrero...), necesitarías hacer una conversión previa con REPLACE o una tabla de equivalencias.
Conversiones parciales
STR_TO_DATE puede extraer solo una parte de la fecha. Si el formato solo especifica componentes de hora, el resultado es un valor TIME:
SELECT
STR_TO_DATE('14:30:00', '%H:%i:%s') AS solo_hora,
STR_TO_DATE('2:30 PM', '%h:%i %p') AS hora_ampm,
STR_TO_DATE('2025', '%Y') AS solo_anio;| solo_hora | hora_ampm | solo_anio |
|---|---|---|
| 14:30:00 | 14:30:00 | 2025-00-00 |
Cuando solo se proporciona el año, MySQL completa con ceros para el mes y el día. Este comportamiento es útil cuando solo necesitas extraer ciertos componentes del texto.
STR_TO_DATE con NULL y valores inválidos
Cuando la cadena no coincide con el formato esperado, o cuando alguno de los argumentos es NULL, la función devuelve NULL:
SELECT
STR_TO_DATE(NULL, '%d/%m/%Y') AS cadena_nula,
STR_TO_DATE('15/06/2025', NULL) AS formato_nulo,
STR_TO_DATE('no-es-fecha', '%d/%m/%Y') AS formato_no_coincide,
STR_TO_DATE('31/02/2025', '%d/%m/%Y') AS fecha_imposible;| cadena_nula | formato_nulo | formato_no_coincide | fecha_imposible |
|---|---|---|---|
| NULL | NULL | NULL | NULL |
El 31 de febrero no existe, así que STR_TO_DATE devuelve NULL. Este comportamiento de validación implícita es útil para detectar fechas inválidas en datos importados.
Combinación con otras funciones
STR_TO_DATE se combina frecuentemente con funciones de manipulación de cadenas para preprocesar datos antes de la conversión. Un caso habitual es limpiar textos con espacios o caracteres extra:
SELECT
texto_original,
STR_TO_DATE(TRIM(texto_original), '%d/%m/%Y') AS fecha_limpia
FROM (
SELECT ' 15/06/2025 ' AS texto_original
UNION SELECT '28/02/2025'
UNION SELECT ' 01/01/2025 '
) datos;| texto_original | fecha_limpia |
|---|---|
| 15/06/2025 | 2025-06-15 |
| 28/02/2025 | 2025-02-28 |
| 01/01/2025 | 2025-01-01 |
Otro patrón útil es combinar STR_TO_DATE con DATE_FORMAT para transformar un formato de fecha a otro en un solo paso:
SELECT
fecha_entrada,
DATE_FORMAT(STR_TO_DATE(fecha_entrada, '%d/%m/%Y'), '%Y-%m-%d') AS iso_format,
DATE_FORMAT(STR_TO_DATE(fecha_entrada, '%d/%m/%Y'), '%W, %M %d, %Y') AS formato_largo
FROM (
SELECT '15/06/2025' AS fecha_entrada
UNION SELECT '01/12/2025'
UNION SELECT '25/03/2025'
) datos;| fecha_entrada | iso_format | formato_largo |
|---|---|---|
| 15/06/2025 | 2025-06-15 | Sunday, June 15, 2025 |
| 01/12/2025 | 2025-12-01 | Monday, December 01, 2025 |
| 25/03/2025 | 2025-03-25 | Tuesday, March 25, 2025 |
La cadena STR_TO_DATE primero convierte el texto en una fecha real, y luego DATE_FORMAT la reformatea al estilo deseado. Este patrón de dos pasos es la forma estándar de convertir entre formatos de fecha en MySQL.
En el siguiente artículo veremos UTC_DATE para trabajar con fechas en hora UTC.
Escrito por Eduardo Lázaro
