sql >> Base de Datos >  >> RDS >> Database

Formato de fecha SQL:cómo manejarlo de manera inteligente

Gracias a la diversidad de culturas en la Tierra, tenemos una variedad de formatos de fecha. Para fechas numéricas, tenemos mes-día-año, día-mes-año y año-mes-día. También disponemos de formatos cortos y largos. Las fechas se pueden mezclar con el tiempo, que es otra historia. Esta realidad nos sigue en el trabajo. Es por eso que el formato de fecha SQL no es algo que podamos tomar con calma.

En Filipinas, usamos 2 formatos:mes-día-año y día-mes-año. Mes-día-año es el formato general para fechas numéricas. Pero con formatos de fecha más largos, usamos indistintamente día-mes-año y mes-día-año.

En el trabajo, nunca encontré una configuración de formato de fecha de SQL Server que no sea mes-día-año. Sin embargo, varía en los informes y archivos para el intercambio de datos y el proyecto Extraer-Transformar-Cargar (ETL). ¡Y mucho menos los usuarios que lo cambian en sus estaciones por preferencias personales! Con todos estos escenarios, no lidiar con ellos adecuadamente es una receta para romper.

¿Sus aplicaciones tratan con diferentes culturas? Ese es otro nivel de complejidad y un problema cuando se trata de estos diversos formatos de fecha SQL. En este artículo, exploraremos el estándar para tratar con todas estas variedades y ejemplos. ¡Sigue leyendo hasta el final! Pero antes de continuar, tomemos un breve desvío sobre cómo SQL Server almacena las fechas.

Cómo SQL Server almacena fechas

Adivina. ¿SQL Server almacena el 29/03/2021 21:35 como está en la base de datos? ¿Qué tal 2021-03-29? ¿Se almacenan como cadenas formateadas? Según esta documentación de Microsoft, no es así.

Tomemos el tipo de datos DATE, por ejemplo. Se almacena como un entero de 3 bytes.

¿Cómo lo sabemos?

Pues Microsoft dice que es así pero no aporta más información. No significa que no podamos saberlo con certeza. En primer lugar, el valor mínimo del tipo de datos DATE es 01/01/0001 o 1 de enero, 1 CE o Era común. Para convertir esto en un número entero, primero convertimos esa fecha en VARBINARIO, así:

SELECT CAST(CAST('01/01/0001' AS DATE) AS VARBINARY(3))

El resultado es 0x000000 en formato hexadecimal. A partir de este valor, podemos ver que el valor entero del 1 de enero de 1 CE es 0. Es lógico porque ese es el valor mínimo de FECHA.

Ahora, avanzamos 1 día.

SELECT CAST(CAST('01/02/0001' AS DATE) AS VARBINARY(3))  -- January 2, 1 CE

El resultado es 0x010000 . Esto es un poco complicado, pero esta publicación nos dio una idea. No podemos tratarlo como lo vemos. Los bytes están invertidos y el valor hexadecimal real es 0x000001 . Si sabe un poco sobre los números hexadecimales, sabe que esto es igual a 1:es 1 día desde el punto de partida, el 1 de enero de 1 EC.

Ahora, probemos con una fecha reciente:29/03/2021.

SELECT CAST(CAST('03/29/2021' AS DATE) AS VARBINARY(3))

El resultado es 0x55420B . Cuando lo invertimos, se convierte en 0x0B4255 . Esta vez, no podemos saber el valor mirándolo. Entonces, lo multiplicamos por 1 como un número entero.

SELECT 0x0B4255 * CAST(1 AS INT)

El resultado es 737.877 . Este es el número de días desde el 1 de enero de 1 EC. Verifiquémoslo con DATEDIFF.

SELECT DATEDIFF(DAY,CAST('01/01/0001' AS DATE),CAST('03/29/2021' AS DATE))

El resultado es el mismo:737.877 dias. ¡Muy genial!

En pocas palabras:la fecha formateada es solo para fines de presentación

Así es como SQL Server almacena los tipos de datos DATE. Es diferente para DATETIME, SMALLDATETIME y DATETIME2, pero aún se almacena como números enteros. SQL Server calcula la duración del tiempo desde el punto de partida y muestra la fecha que todos podemos entender.

Ya sea que lo esté viendo en SQL Server Management Studio, dbForge Studio para SQL Server o su aplicación, 29/03/2021 es solo una presentación. Si cambia la región o el idioma, el valor almacenado 0x55420B seguirá siendo el mismo.

Ahora sabemos que las fechas no se almacenan como cadenas. Podemos olvidarnos de almacenar fechas en un formato específico . Así no es como funciona de todos modos. En su lugar, veamos diferentes formas en SQL para formatear las fechas que necesitan sus aplicaciones.

Las 4 formas fáciles de formatear fechas

Examinemos las siguientes funciones de fecha SQL:

  • Función CONVERTIR
  • ESTABLECER IDIOMA
  • ESTABLECER FORMATO DE FECHA
  • Función FORMATO

También puede usar un formateador de consultas SQL.

1. Función CONVERTIR

CONVERT es una de las funciones de conversión de datos que también puede servir para formatear fechas. La Figura 1 muestra un ejemplo.

Los primeros dos argumentos de CONVERT son el tipo de datos de destino y el valor de fecha. El tercero es opcional pero también se aplica a las fechas. Los valores numéricos son los estilos de formato de fecha SQL que se usarán durante la conversión de fecha a cadena.

En la Figura 1, Japón usa un formato de año-mes-día con una barra como separador. Alemania usa día-mes-año con puntos como separadores. Gran Bretaña y Francia usan la misma secuencia que Alemania, pero con una barra como separador. Solo Estados Unidos usa mes-día-año con un guión como separador.

En SQL, también puede convertir la expresión DATETIME a DATE.

Para obtener una lista completa de los estilos de formato de fecha CONVERT en SQL, consulte esta referencia de Microsoft.

2. ESTABLECER IDIOMA

Esta configuración especifica el idioma aplicado a la sesión. Afecta a los formatos de fecha y mensajes del sistema. Cuando establece un idioma, también aplica implícitamente la configuración SET DATEFORMAT (lo resolveremos más adelante).

Por ahora, veamos los ejemplos en la Figura 2. Voy a cambiar la configuración de idioma a lituano y luego a inglés.

Mire la Figura 2. El formato de fecha lituano es año-mes-día. Cada vez que pruebo fechas diferentes, la fecha larga siempre incluye 'm.' antes del mes y 'd.' después del día. La primera letra del mes y el nombre del día de la semana tampoco se escriben con mayúscula. Es diferente para otras configuraciones de idioma, pero entiendes el punto.

Para obtener más información sobre CONFIGURAR IDIOMA, consulte esta referencia de Microsoft.

3. ESTABLECER FORMATO DE FECHA

Esta configuración coloca el orden del mes, día y año para interpretar cadenas de caracteres de fecha. Anulará la configuración de formato de fecha implícita realizada por SET LANGUAGE. Aquí hay un ejemplo en la Figura 3.

En la Figura 3, el código usa el formato DMY o día-mes-año. Bajo esta configuración, cualquier valor de fecha establecido en una variable de fecha debe seguir este patrón. 30/03/2021 coincide con este formato, pero 03/31/2021 genera un error porque 31 no es un mes válido.

Por lo tanto, los cambios en el formato de fecha pueden dañar su aplicación si la lógica opera bajo la premisa de otro formato.

Para obtener más información sobre SET DATEFORMAT, consulte esta referencia de Microsoft.

4. Función FORMATO

De todas las opciones de formato disponibles, esta es la más flexible. Es similar para el formato de fecha en .Net, ya que FORMAT se basa en la presencia de .Net Framework en el servidor donde está instalado SQL Server. Sin embargo, ese es el inconveniente de esta opción.

Al igual que hacerlo en C#, FORMAT toma un valor de fecha y una cadena de formato. Veamos algunos ejemplos en la Figura 4.

Al igual que en .Net, en SQL Server, puede formatear fechas usando diferentes separadores. Además, puede colocar el mes, el día y el año en cualquier lugar. Luego, puede obtener la información cultural y usar su formato de fecha.

Para obtener más información y ejemplos sobre FORMATO, consulte esta referencia de Microsoft.

Ahora, hemos identificado 4 formas de dar formato a las fechas y la variedad de formatos de fecha. ¿Existe un formato estándar que siempre funcione al convertir cadenas en fechas?

ISO 8601:el formato de fecha SQL más portátil y libre de errores que puede usar para la conversión

ISO 8601 existe desde 1988. Es el estándar internacional en los intercambios de datos relativos a fechas y horas .

También está disponible en la función CONVERTIR como uno de los estilos de formato de fecha:los estilos 126 y 127 cumplen con la norma ISO 8601.

¿Qué lo hace portátil y libre de errores?

El problema con los formatos que no son ISO 8601

Demostremos el problema para los que no son ISO 8601 con un ejemplo:

DECLARE @d VARCHAR(10) = '03/09/2021';

SET LANGUAGE Italian;
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET LANGUAGE English
SELECT FORMAT(CONVERT(DATETIME, @d),'D')

SET DATEFORMAT DMY
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET DATEFORMAT MDY
SELECT FORMAT(CONVERT(DATETIME, @d),'D')

Dependiendo de su ubicación de fecha, puede interpretar @d como 9 de marzo de 2021 o 3 de septiembre de 2021. No puede estar seguro de cuál es cuál. Ahí es donde radica el problema.

Verifique el resultado en la Figura 5 a continuación:

¡Incluso SQL Server no lo sabe con seguridad!

Peor aún, este tipo de escenario puede romper su aplicación como sucedió en la Figura 3 anterior. Esta situación es problemática para las aplicaciones que tratan con usuarios multiculturales.

¿ISO 8601 puede ayudar con esto?

Uso de ISO 8601 para solucionar problemas de formato

Observe cuando el formato ISO 8601 yyyyMMdd se usa en lugar de MM/dd/yyyy y verifique el resultado en la Figura 6:

Siempre será el 9 de marzo, independientemente de la configuración de idioma y formato de fecha que se utilice. Esto es excelente para el intercambio de datos y la integración de sistemas. Si tu usuario tiene otro formato de fecha en la estación, tampoco importará.

Si necesita transformar sus fechas en cadenas y viceversa, use ISO 8601.

ISO 8601 en SQL Server viene en 2 versiones:

  • AAAAMMDD es solo para fechas.
  • AAAA-MM-DDTHH:MM:SS para una combinación de fecha y hora, donde T es el delimitador entre fecha y hora.

Otras formas de manejar formatos de fecha de aplicaciones a SQL Server

1. Usar controles de reconocimiento de fecha en la aplicación

Cuando le pide a un usuario que ingrese fechas en un formulario, no permita que use texto libre. Use controles de fecha que permitan elegir solo entre valores válidos.

2. Convierta a un formato diferente solo cuando sea necesario

No sigas transformando fechas en cadenas y viceversa. Utilice los tipos de datos de fecha o fecha y hora nativos de la aplicación de llamadas. Si necesita transformarlos por cualquier motivo, use ISO 8601.

3. Configure la fecha/hora, la zona horaria y la cultura en el inicio de su aplicación, si corresponde

Si su aplicación utiliza un formato de fecha fijo y a sus usuarios les encanta modificar los formatos de fecha, puede corregir ambos al iniciar la aplicación. Establezca explícitamente lo que su aplicación necesita. Será mucho mejor si su administrador de red puede bloquear esta configuración.

Puntos para llevar

Entonces, ¿es abrumador manejar variedades de formato de fecha SQL? No puedo culparte si todavía lo encuentras así, pero hemos descubierto que no es imposible.

Esto es lo que hemos cubierto:

  • Las fechas SQL se almacenan como números enteros . Lo que vemos con nuestros ojos ya está formateado según la configuración de SQL Server. No importa cuántas veces cambiemos el idioma y los formatos de fecha, el valor almacenado seguirá siendo el mismo. Es inútil pensar en almacenar fechas en un formato específico.
  • Hay 4 formas de dar formato a las fechas:CONVERTIR , ESTABLECER IDIOMA , ESTABLECER FORMATO DE FECHA y FORMATO .
  • Si necesita transformar fechas en cadenas y viceversa, utilice el formato ISO 8601 .
  • Hay otras 3 formas de manejar los formatos de fecha:
    • uso de controles basados ​​en fechas en su aplicación;
    • transformar fechas en cadenas solo cuando sea necesario;
    • establecer la zona horaria requerida, cultura, fecha/hora del servidor al inicio cuando corresponda .

¿Crees que esto será útil para ti y para los demás? Luego, comparta este artículo en sus plataformas de redes sociales favoritas.