En una aplicación web típica, las fechas se recuperan de la capa de la base de datos fuertemente tipada (por ejemplo, en c # como System.DateTime como System.String opuesto).
Cuando una fecha debe expresarse como una cadena (por ejemplo, mostrada en una página), la conversión de DateTime a cadena se realiza en el nivel de presentación.
¿Por qué es esto? ¿Por qué es malo convertir el DateTime en una cadena en el nivel de la base de datos?
Vea también el acalorado debate en el chat y la pregunta original que inició todo esto .
database
sql
formatting
John Wu
fuente
fuente
Respuestas:
Las fechas, fechas y realmente cualquier otro objeto escrito, generalmente deben dejarse en su formato escrito correctamente hasta el momento en que necesite que se conviertan en otro tipo, especialmente cuando ese tipo es una forma legible por humanos, y especialmente cuando es una pérdida / tipo de conversión unidireccional.
¿Por qué? Debido a que se supone que el tipo le brinda muchas funciones prácticas incorporadas, como pruebas de igualdad adecuadas, suma y resta, comparación (mayor que, menor que), zona horaria y funcionalidad local (especialmente importante para cualquier cosa relacionada con el tiempo), etc. Si decide que desea apoyar a los estadounidenses y el formato "Mes Día [th], Año", así como el estilo británico común de "Día Mes Año", o el estándar ISO de "Año-Mes-Día"? ¿Qué haría si fuera una cadena y necesitara hacer ese cambio, analizarlo nuevamente en una Fecha? Uf, no, gracias, hay muchos males y errores horribles de esa manera, que es mejor evitarlos por completo.
Más específicamente, mencionó la arquitectura escalonada, que tiene la capa de presentación separada de los datos más adelante. Esta es en realidad la otra gran razón para pasar una Fecha como Fecha y no una cadena, porque ¿en qué tipo de formato de cadena se debe poner la fecha? Inglés, chino, con o sin segundos / milisegundos, nombre completo del mes o dígitos, ¿querrá ordenar en el campo de fecha más tarde (la ordenación de una cadena exige un cierto formato de cadena si desea que funcione correctamente), etc.? Todo esto es una cuestión de presentación, cómo el usuario debe ver los datos, y poner esa lógica en cualquier otro lugar limitaría la ventaja de tener una arquitectura escalonada en primer lugar. La base de datos no debería necesitar saber o importar cómo querrá ver la fecha en el futuro.
Finalmente, casi todas las aplicaciones complejas (que es para lo que son las arquitecturas escalonadas) que se preocupan por el tiempo inevitablemente usarán horas / fechas de muchas, muchas maneras diferentes, y a menudo en todos los niveles diferentes de la arquitectura. Los objetos mecanografiados relacionados con horas y fechas existen por una muy buena razón: el tiempo mismo, y especialmente los sistemas de calendario humanos, son raros y difíciles. En última instancia, los tiempos y las fechas no son cadenas por la misma razón que los enteros y los puntos flotantes no son cadenas, y solo hará que su vida sea más difícil si intenta fingir que en realidad son solo matrices de caracteres, porque simplemente no lo son.
fuente
Why? Because it is assumed that the type provides you with lots of handy built in functionality
En mi opinión, esto es solo secundario. La verdadera razón es que el tipo te dice qué es algo . Una fecha no es una cadena, simplemente se traduce fácilmente en una cadena legible por humanos.Quiero saber el tipo
Realmente no me importa si su base de datos almacena información en una cadena, algunas entradas o bytes, porque, al final, siempre son bytes de todos modos. Esa cadena que ocupa más espacio del necesario en su base de datos no me molesta. Lo que me molesta es encontrarse con fechas como esta:
10/11/2016
Y sin saber si ese es el undécimo mes o el décimo mes.
Pero está validado, dices. Seguro que lo pones a través de procesos de validación. La fecha es perfectamente correcta. Pero aquí estoy manteniendo esto y todo lo que sé es que la fecha es una cadena. Ni siquiera puedo decirte qué fecha es esta.
"Décimo día de noviembre del año dos mil dieciseisavo de nuestro señor".
Eso es una cuerda. Una de nuestras presentaciones lo necesita en ese formato. Usted dijo que la base de datos convierte todas las fechas en cadenas, ¿verdad? Divertirse con eso.
El trabajo de la base de datos es almacenar datos no presentes. Claro, puede hacerlo en cadenas, pero luego debe analizarlo para que sea útil presentarlo en otros formatos. Almacenarlo en una forma analizada estándar para cualquier tipo que ofrezca la base de datos nos permite estar tan listos para presentar como podamos sin haber tomado una decisión de presentación. Realmente no me importa si la base de datos respalda ese tipo con una cadena o entradas o bytes. Mientras sepa lo que está haciendo.
Pero cuando no le hace saber al DB que estamos tratando con una fecha y almacenamos una fecha como una cadena, está presentando prematuramente y favoreciendo una presentación sobre todas las demás. Esto obliga a todos los demás presentadores a analizar antes de convertir. No, la base de datos no es parte de la capa de presentación. No pidas que sea.
Del mismo modo, la capa de presentación no forma parte de la base de datos, por lo que no es aconsejable acoplar un informe a los detalles de la base de datos. Es mucho más robusto actuar según los tipos.
fuente
Lugar
La conversión de la fecha en una cadena para fines de presentación requiere conocer las preferencias del usuario, ya que la misma fecha en general generalmente se debe mostrar de manera diferente para los usuarios en diferentes lugares. Incluso si usa una configuración regional única en su aplicación, el comportamiento adecuado debe usar la configuración regional de la aplicación en lugar del servidor de la base de datos; y no se garantiza que sean idénticos incluso si en este momento coinciden.
La conversión de un tipo de datos de fecha universal a una cadena específica de la localidad debe ocurrir en la capa de presentación porque es la capa que sabe cómo se debe realizar esa conversión.
fuente
Esto no es deseable por la misma razón por la que no querría convertir ciegamente cualquier tipo a una cadena tan pronto como llegue al nivel de la aplicación. Existe una alta probabilidad de que desee utilizar ese objeto de alguna manera antes de presentarlo al usuario (si incluso se lo presenta al usuario). Para este ejemplo específico, imagine que necesita hacer algo de matemática de fechas en el objeto. No hay inconveniente en convertir el objeto en una cadena precisamente antes de mostrarlo.
fuente
Los tipos existen por una razón, si no agregaran ningún beneficio, entonces no los tendríamos y no los usaríamos y simplemente tendríamos "el tipo" y todo sería eso. No solo son convenientes, sino que también agregan seguridad y eficiencia. La siguiente es una lista de por qué siempre debe persistir los tipos en su formato nativo y no como cadenas . Usé
DateTime
como ejemplo la mayor parte del tiempo, pero los mismos principios se aplican a cualquier tipo primitivo como enteros, decimales, binarios, etc.Almacén de datos
Restricciones
Restricción de tipo
Casi todos los almacenes de datos permiten especificar restricciones en los datos, esto incluye restricciones de tipo. Uno de los principales beneficios de especificar una
DateTime
instancia es que los datos almacenados estarán restringidos a ese tipo. Nunca será posible ingresar nada que no sea una fecha y hora, independientemente de cómo se insertaron los datos en la tienda. Esto último es importante para sistemas más grandes donde existen múltiples procesos que interactúan directamente con la tienda. Esto también incluye tratar de agregar fechas defectuosas como el 30 de febrero (de cualquier año) ya que febrero solo puede tener 29 días en un año bisiesto y 28 días para los años no bisiestos.Restricciones de validación
También hay restricciones de validación que se pueden implementar en el Almacén de datos, como garantizar que una fecha insertada no supere la fecha actual o que se produzca una fecha de inicio anterior a una fecha de finalización.
Operaciones
La mayoría de los almacenes de datos también tienen operaciones / funciones integradas como
DateAdd
oDatePart
en MS Sql Server. Esto le permite comenzar a filtrar o seleccionar datos específicos mientras los datos todavía están en la tienda (aún no se han recuperado en la aplicación).Formato universalmente aceptado
Al usar el tipo nativo, otros desarrolladores o sistemas que también interactúan con la tienda no tienen que estar informados sobre los detalles minuciosos de cómo se almacena ese tipo primitivo. Este no es el caso si ese tipo se almacenó como una cadena, entonces debe asegurarse de que todos entiendan el formato de esa
DateTime
representación de cadena. Este sistema se vuelve frágil cuando se trata de datos que abarcan entornos locales, regiones y culturas en el origen de datos, la ubicación física de una aplicación y los atributos del usuario / sistema final que está interactuando con esos datos. Ejemplo: el formato de fecha en un país podría ser MM / dd / aaaa (como en los EE. UU.) Pero en otro podría ser dd / MM / aaaa, detectar esa diferencia se vuelve casi imposible.Velocidad
La velocidad de recuperación, la velocidad de validación, la velocidad de las operaciones y la eficiencia del almacenamiento también son factores importantes. Ejemplo de la velocidad de recuperación: los almacenes de datos permiten índices en columnas y estos índices generalmente se pueden usar de manera más eficiente si el tipo se almacena en su formato nativo.
Solicitud
Acceso a los datos
Ejecutar consultas en la tienda se vuelve más simple usando el sistema de tipo nativo ya que los desarrolladores, una vez más, no tienen que adivinar el formato de almacenamiento. Casi todos los proveedores de aplicaciones de almacenamiento de datos ( ejemplo: ado.net ) proporcionan mecanismos para crear las consultas parametrizadas adecuadas en función de los tipos nativos pasados. Aquí hay un ejemplo de cómo agregar la parte Fecha a una consulta ado.net en un almacén de SQL Server, hacer lo mismo con las cadenas sería muy engorroso y frágil / propenso a errores.
Operaciones
Los tipos nativos en el código también proporcionan operaciones estándar como el tipo .net
System.Date
. Las operaciones suelen ser de naturaleza matemática, como agregar fechas, encontrar la diferencia entre fechas, etc. Nuevamente, esto no es posible hacerlo fácilmente en los tipos de cadena.Capa de presentación
Lugar
Cuando un tipo primitivo finalmente se convierte en una cadena en la capa de presentación ( la ubicación correcta en la pila de programas para hacerlo ) el programador ahora tiene varias opciones para mostrarlo correctamente de acuerdo con el contexto en el que se presenta. Este contexto generalmente consiste en el significado real de los datos y la configuración regional del usuario.
Ejemplo 1Una instancia de fecha y hora se puede formatear automáticamente en función de la configuración regional del usuario.
Ejemplo 2Una instancia decimal podría representar una cantidad (moneda) y la configuración regional del usuario también debería mostrar la cantidad de acuerdo con sus preferencias. Una aplicación de C # podría mostrar el valor usando
Esto podría ser crítico ya que las diferentes culturas muestran los números de manera diferente. En el período de EE. UU. (.) Y la coma (,) tienen el significado inverso exacto que en los Países Bajos.
Ubicación
Esto es muy específico para las
DateTime
instancias. Una fecha y hora representan una ocurrencia en un momento específico en el tiempo, pero esto generalmente tiene que ser transmitido / presentado al usuario dependiendo de su propia zona horaria. Ejemplo: unaDateTime
instancia2016-09-21T23:38:21.399Z
podría mostrarse como9/21/2016 5:21 PM
para un usuario en la zona horaria del este de los EE. UU. Hay muchas maneras de lograr esto, pero se vuelve casi imposible si la instancia de fecha y hora se mantiene en la memoria como un tipo de cadena o en el almacén de datos como un tipo de cadena.Regla general
Las 2 reglas generales para una aplicación que se siguen cuando se trata de convertir cualquier tipo primitivo en una representación de cadena son las siguientes
fuente
Realmente no hay nada de malo en hacer esto (se hace todo el tiempo en los servicios) siempre que esté utilizando un formato no ambiguo para su fecha. Por inequívoco, quiero decir que no solo la fecha está clara (por ejemplo, MM / DD vs. DD / MM) sino también en qué zona horaria está. Así que, por adelantado, si va a representar sus fechas como texto, use un formato ISO . Prefiero las cadenas de tiempo basadas en UTC.
Pros:
Contras:
Si alguien dijera que quería hacer esto, le preguntaría "¿por qué?" porque realmente no tiene mucho sentido. Si la razón por la que alguien quiere devolver la fecha como una Cadena es porque simplemente la mostrará directamente, esta no es una buena razón para usar Cadenas de la base de datos.
fuente