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_europeoformato_americanoformato_puntos
2025-06-152025-06-152025-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_horacon_ampm
2025-06-15 14:30:002025-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;
clientefecha_textofecha_mysqldias_desde
Ana López15/01/20252025-01-15154
Carlos Ruiz28/02/20252025-02-28110
María García03/06/20252025-06-0315
Pedro Sánchez31/12/20242024-12-31169

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_rawfecha_limpia
15/06/20252025-06-15
2025-06-152025-06-15
June 15, 20252025-06-15
formato_raroNULL

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_completomes_abreviadosolo_mes_anio
2025-01-152025-01-152025-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_horahora_ampmsolo_anio
14:30:0014:30:002025-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_nulaformato_nuloformato_no_coincidefecha_imposible
NULLNULLNULLNULL

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_originalfecha_limpia
15/06/20252025-06-15
28/02/20252025-02-28
01/01/20252025-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_entradaiso_formatformato_largo
15/06/20252025-06-15Sunday, June 15, 2025
01/12/20252025-12-01Monday, December 01, 2025
25/03/20252025-03-25Tuesday, 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