Pourquoi ne pas renvoyer les dates sous forme de chaîne à partir de la base de données?

41

Dans une application Web typique, les dates sont extraites de la couche de base de données fortement typée (par exemple, en c # sous la forme System.DateTime ou System.String, par opposition).

Lorsqu'une date doit être exprimée sous forme de chaîne (par exemple affichée sur une page), la conversion de DateTime en chaîne est effectuée dans le niveau présentation.

Pourquoi est-ce? Pourquoi est-ce une mauvaise chose de convertir DateTime en chaîne sur le niveau base de données?

Voir aussi le débat houleux sur le chat et la question initiale qui a déclenché tout cela .

John Wu
la source
73
Laissez-moi vous demander ceci: voulez-vous simplement convertir chaque type en chaîne? Qu'est-ce qui rend Date différent?
Gardenhead
7
Bonne question! S'il vous plaît voir le débat animé en cours, ici .
John Wu
8
Eh bien, il semble assez évident que l'autre gars a tort et que tout le monde a raison. Pas vraiment une question ici
gardenhead
7
Parfois, vous devez faire des maths en dehors de la base de données. Considérablement plus difficile si tout ce que vous avez est des chaînes.
Eric King
14
Un autre problème - de quel type de ficelle avez-vous besoin? Il y a beaucoup de façons de représenter une date / heure sous forme de chaîne. Et si j'avais une base de données qui ne renvoyait que l'heure actuelle, représentée sous la forme d'un nombre de secondes depuis l'époque, sous forme de chaîne (par exemple, l'heure actuelle est "1474496980"). Cela serait-il utile? Voudriez-vous utiliser une base de données comme celle-là?
riwalk

Réponses:

168

Dates, DateTimes et tout autre objet typé doivent généralement être conservés dans leur format correctement typé jusqu'au moment où ils doivent être transformés en un autre type - en particulier lorsque ce type est une forme lisible par l'homme, et en particulier lorsqu'il s'agit d'une perte / sorte de conversion à sens unique.

Pourquoi? Parce qu'il est supposé que le type vous fournit de nombreuses fonctionnalités intégrées pratiques, telles que des tests d'égalité appropriés, des additions et des soustractions, des comparaisons (supérieures à, inférieures à), des fonctionnalités de fuseau horaire et de paramètres régionaux (particulièrement importantes pour les événements liés au temps), etc. Si vous décidez de soutenir les Américains et le format "Mois Jour [Année]" ainsi que le style britannique courant "Jour Mois Année" ou la norme ISO "Année-Mois-Jour"? Que feriez-vous si c'était une chaîne et que vous deviez effectuer ce changement, le réanalyser dans une Date? Ugh, non merci - il y a beaucoup de maux et d'insectes ignobles de cette façon, qu'il vaut mieux éviter complètement.

Plus précisément, vous avez mentionné l’architecture à plusieurs niveaux, dans laquelle la couche de présentation est séparée des données ultérieurement. C’est en fait l’autre grande raison de passer une date en tant que date et non une chaîne - car quel type de formatage de chaîne faut-il insérer dans la date? Anglais, chinois, avec ou sans secondes / millisecondes, nom du mois complet ou chiffres, voulez-vous trier le champ de date plus tard (le tri sur une chaîne nécessite un certain format de chaîne si vous voulez que cela fonctionne correctement), etc.? Tout est une question de présentation - comment l’utilisateur doit visualiser les données - et le fait de placer cette logique ailleurs ne limiterait l’avantage d’avoir une architecture à plusieurs niveaux. La base de données ne devrait pas avoir besoin de savoir ou de se préoccuper de la façon dont vous voulez voir la date dans le futur.

Enfin, presque toutes les applications complexes (qui correspondent aux architectures multi-niveaux) qui tiennent compte du temps utilisent inévitablement les temps / dates de nombreuses manières différentes, et souvent à tous les niveaux de l’architecture. Les objets typés liés aux heures et aux dates existent pour une très bonne raison: le temps lui-même, et particulièrement les systèmes de calendrier humain, sont étranges et difficiles. En fin de compte, les heures et les dates ne sont pas des chaînes pour la même raison que les entiers et les points flottants ne le sont pas. Cela ne vous rendra la vie plus difficile si vous essayez de prétendre qu'ils ne sont en réalité que des tableaux de caractères, car ils ne le sont tout simplement pas.

BrianH
la source
26
+1 juste pour utiliser le mot ignoble. Je suis d’accord avec vos arguments convaincants et votre explication détaillée, mais c’est pourquoi j’ai dû ouvrir une session et voter pour vous.
Adrian Larson
1
Représenter la date et l'heure en secondes depuis une heure définie dans le passé est également robuste entre différents calendriers. Par exemple, les calendriers islamiques et chinois n'utilisent pas les mois, le numéro d'année, etc. Greogrian. Je considérerais cela comme une mauvaise pratique.
rexkogitans
Les dates sont souvent présentées comme "il y a X jours". Bonne chance pour ré-analyser cette valeur.
Agent_L
5
N'oublions pas non plus les problèmes de modification de l'heure d'été (et d'autres problèmes similaires). Est-ce que "6 nov. 2016 01:30:26" sera la première fois ou la deuxième fois que cette date et cette heure sont passées? UTC DateTime est au moins unique et vous pouvez toujours le traduire dans la représentation locale pour cette période - il n'est pas toujours possible de revenir en arrière.
J ...
3
Why? Because it is assumed that the type provides you with lots of handy built in functionalityA mon avis, ce n'est que secondaire. La vraie raison est que le type vous dit ce que quelque chose est . Une date n'est pas une chaîne, il se trouve qu'elle se traduit facilement par une chaîne lisible par l'homme.
Doval
53

Il dit d'utiliser le serveur Web pour convertir l'heure des données en chaîne. Je dis le faire sur le serveur de base de données et non sur le serveur Web. Pourquoi pensez-vous que c'est mieux? - Tête MT

Je veux savoir le type.

Je ne me soucie vraiment pas de savoir si votre base de données stocke des informations dans une chaîne, des entiers ou des octets, car, finalement, il s'agit toujours d'octets. Cette chaîne prenant plus de place que nécessaire dans votre base de données ne me dérange pas. Ce qui me dérange, ce sont des dates comme celle-ci:

11/10/2016

Et ne sachant pas si c'est le onzième mois ou le dixième mois.

Mais c'est validé tu dis. Bien sûr, vous le soumettez à un processus de validation. La date est parfaitement correcte. Mais ici je maintiens cette chose et tout ce que je sais, c'est que la date est une chaîne. Je ne peux même pas vous dire quelle date c'est.

"Le dixième jour de novembre de l'an deux mille seizième de notre seigneur."

C'est une ficelle. Une de nos présentations en a besoin dans ce format. Vous avez dit que la base de données convertit toutes les dates en chaînes, n'est-ce pas? Amusez-vous avec ça.

Le travail de la base de données consiste à stocker des données qui ne sont pas présentes. Bien sûr, vous pouvez le faire en chaîne mais vous devez ensuite l’analyser pour le rendre utile à présenter pour d’autres formats. Le stockage sous une forme analysée standard, quel que soit le type proposé par DB, nous permet de présenter le mieux possible, sans avoir pris de décision. Peu importe pour moi si la base de données sauvegarde ce type avec une chaîne ou des entiers ou des octets. Tant qu'il sait ce qu'il fait.

Mais lorsque vous ne signalez pas à la base de données que nous traitons une date et que vous stockez une date sous forme de chaîne, vous présentez prématurément et privilégiez une présentation par rapport à toutes les autres. Cela oblige tous les autres présentateurs à analyser avant la conversion. Non, la base de données ne fait pas partie de la couche de présentation. Ne lui demande pas de l'être.

De même, la couche de présentation ne fait pas partie de la base de données, il n'est donc pas judicieux d'associer un rapport aux détails de la base de données. Il est beaucoup plus robuste d'agir sur les types.

confits_orange
la source
Cette réponse concerne le stockage sous forme de chaînes. Cependant, il ne traite pas du modèle courant de stockage de dates dans un type de date natif, mais le formate ensuite en chaîne dans la requête SQL , à l'aide de fonctions telles que CONVERT (T-SQL), ni qu'un SGBD sérialise généralement ses dates. dans une chaîne dans un format configurable quelle que soit la requête. Par exemple: postgresql.org/docs/9.5/static/…
dcorking le
C'est un rapport. Cela arrive après le stockage. C'est comme convertir ma date de naissance à mon âge.
candied_orange
2
Je voulais simplement vous encourager à élargir votre réponse, car le sujet du PO est comment "les dates sont extraites de la couche base de données". Il existe un modèle bien établi, bien que probablement obsolète, dans lequel un rapport interroge la base de données à la recherche de chaînes de date formatées et localisées. Je pense que le PO aimerait entendre ces arguments de dépréciation. Je sais que je le ferais.
départ le
@dcorking note update.
candied_orange
Ajoutez de l'eau à la scierie: créez simplement un système sur une base installée couvrant plusieurs fuseaux horaires où l'instant absolu est primordial et observez vos résultats avec les conversions de chaîne <-> timestamp partout. Pire encore, demandez aux utilisateurs de créer leurs propres plug-ins et de leur donner des horodatages, car les chaînes voient à quel point ces horodatages seront consistants!
Newtopian
19

Lieu

La conversion de la date en chaîne à des fins de présentation nécessite de connaître les préférences de l'utilisateur, car la même date exacte devrait généralement être affichée différemment pour les utilisateurs de lieux régionaux différents. Même si vous utilisez un seul paramètre régional dans votre application, le comportement approprié doit utiliser les paramètres régionaux de l' application au lieu du serveur de base de données. et ils ne sont pas garantis d'être identiques même si, à ce moment-là, ils sont identiques.

La conversion d'un type de date universel en une chaîne spécifique à l'environnement local doit avoir lieu dans la couche de présentation, car c'est la couche qui sait comment cette conversion doit être effectuée.

Peter est
la source
3
Pour un exemple concret d’inadéquation des paramètres régionaux, imaginez que vous écriviez une application pour les utilisateurs du Maine, aux États-Unis, puis que celle-ci soit hébergée dans la batterie de serveurs de la côte ouest d’Amazon. ;) Ce n'est pas si improbable, en fait.
jpmc26
@ jpmc26 Je ne comprends pas la différence - le Maine utilise-t-il un format de date différent du reste des États-Unis?
Pete Kirkham
2
@PeteKirkham Maine et la côte ouest des États-Unis utilisent des fuseaux horaires distants de 3 heures.
jpmc26
1
Ou encore un autre scénario: imaginez que vous utilisiez un serveur en Suisse qui doit desservir des clients dans quatre langues différentes (allemand, français, italien, anglais) avec des paramètres régionaux différents (et des règles de formatage légèrement différentes). Bonne chance pour choisir le bon endroit pour votre serveur dans une telle situation.
Voo
1
@ jpmc26 Les fuseaux horaires et les paramètres régionaux ne sont pas la même chose. Par exemple, nous avons des bureaux à Glasgow, en Écosse, à Atlanta, aux États-Unis et à Pune, en Inde. Les consultants de ces bureaux surveillent tour à tour les sites (campus, hôpitaux, hôtels, etc.) dans le monde entier. La base de données d'application fonctionne au format UTC, mais affiche les heures en heure locale du site surveillé. Les consultants des États-Unis ont des dates localisées au format MM / JJ / AAAA, mais les paramètres régionaux britanniques et indiens sont JJ ​​/ MM / AAAA - cela dépend des paramètres régionaux, pas du fuseau horaire du site ou de l'utilisateur.
Pete Kirkham
9

Cela n’est pas souhaitable pour la même raison, vous ne voudriez pas simplement convertir aveuglément un type en chaîne dès qu’il atteindra le niveau application. Il est fort probable que vous souhaitiez utiliser cet objet avant de le présenter à l'utilisateur (si vous le présentez même à l'utilisateur). Pour cet exemple spécifique, imaginez que vous deviez faire un calcul de date avec l'objet. Il n’ya pas d’inconvénient à convertir simplement l’objet en chaîne avant de l’afficher.

tête de jardin
la source
4

Les types existent pour une raison, s'ils n'apportaient aucun avantage, nous ne les aurions pas et ne les utiliserions pas. Nous aurions simplement "le type" et tout serait comme ça. Ils ne sont pas seulement pratiques, ils ajoutent également sécurité et efficacité. Vous trouverez ci-dessous une liste des raisons pour lesquelles vous devez toujours conserver les types dans leur format natif et non sous forme de chaîne . La DateTimeplupart du temps, j'ai utilisé l'exemple, mais les mêmes principes s'appliquent à tous les types primitifs tels que les entiers, les nombres décimaux, les valeurs binaires, etc.


Magasin de données

Contraintes

Type de contrainte

Presque tous les magasins de données permettent de spécifier des contraintes sur les données, ceci inclut les contraintes de type. L'un des principaux avantages de la spécification d'une DateTimeinstance est que les données stockées seront limitées à ce type. Il ne sera jamais possible de saisir quoi que ce soit autre que la date et l'heure, quelle que soit la manière dont les données ont été insérées dans le magasin. Ce dernier point est important pour les systèmes plus grands où plusieurs processus interagissent directement avec le magasin. Cela implique également d’ajouter des dates erronées comme le 30 février (d’une année à l’autre), car février ne peut compter que 29 jours sur une année bissextile et 28 jours pour les années non bissextiles.

Contraintes de validation

Il existe également des contraintes de validation pouvant être implémentées dans le magasin de données, telles que le fait de s'assurer qu'une date insérée ne dépasse pas la date actuelle ou qu'une date de début survient avant une date de fin.

Opérations

La plupart des magasins de données ont également des opérations / fonctions intégrées telles que DateAddou DatePartdans MS Sql Server. Cela vous permet de commencer à filtrer ou à sélectionner des données spécifiques pendant que les données sont encore dans le magasin (pas encore récupérées dans l'application).

Format universellement accepté

En utilisant le type natif, les autres développeurs ou systèmes qui interagissent également avec le magasin ne doivent pas nécessairement être informés des derniers détails relatifs au stockage de ce type primitif. Ce n'est pas le cas si ce type était stocké sous forme de chaîne, vous devez donc vous assurer que tout le monde comprend le format de cette DateTimereprésentation. Ce système devient fragile lorsqu'il traite des données couvrant les paramètres régionaux, les régions et les cultures d'origine, l'emplacement physique d'une application et les attributs de l'utilisateur final / du système qui interagit avec ces données. Exemple: le format de date dans un pays peut être MM / jj / aaaa (comme aux États-Unis) mais dans un autre pays, jj / mm / aaaa, détecter cette différence devient presque impossible.

La vitesse

La rapidité de récupération, la validation, la rapidité des opérations et l'efficacité du stockage sont également des facteurs importants. Exemple de vitesse de récupération: les magasins de données autorisent les index sur les colonnes et ces index peuvent généralement être utilisés plus efficacement si le type est stocké dans son format natif.

Application

Accès aux données

L'exécution de requêtes sur le magasin devient plus simple en utilisant le système de type natif car les développeurs, encore une fois, n'ont pas à deviner le format de stockage. Presque tous les fournisseurs d’applications de magasin de données ( exemple: ado.net ) fournissent des mécanismes permettant de créer les requêtes paramétrées appropriées en fonction des types natifs transmis. Voici un exemple d’ajout de la partie Date à une requête ado.net dans un magasin Sql Server, faire la même chose avec des chaînes serait très encombrant et fragile / sujet aux erreurs.

command.Parameters.Add(new SqlParameter("@startDate", SqlDbType.Date) {Value = myDateInstance.Date});

Opérations

Les types natifs dans le code fournissent également des opérations standard telles que le type .net System.Date. Les opérations sont généralement de nature mathématique, telles que l’ajout de dates, la recherche de la différence entre les dates, etc. Encore une fois, il n’est pas possible de le faire facilement avec des types de chaîne.

Couche de présentation

Lieu

Lorsqu'un type primitif est finalement converti en chaîne dans la couche de présentation ( l'emplacement correct dans la pile de programmes pour le faire ), le programmeur dispose désormais de plusieurs options pour l'afficher correctement en fonction du contexte dans lequel il est présenté. Ce contexte comprend généralement la signification réelle des données et les paramètres régionaux de l'utilisateur.

Exemple 1

Une instance datetime peut être automatiquement formatée en fonction des paramètres régionaux de l'utilisateur.

DateTime.Now.ToString("D", CultureInfo.GetCultureInfo(userContext.Culture))
Exemple 2

Une instance décimale peut représenter un montant (devise) et les paramètres régionaux de l'utilisateur doivent également afficher le montant en fonction de leurs préférences. Une application c # peut alors afficher la valeur à l'aide de

amount.ToString("C", CultureInfo.GetCultureInfo(userContext.Culture))

Cela peut être critique car différentes cultures affichent les chiffres différemment. Aux États-Unis, le point (.) Et la virgule (,) ont exactement le sens inverse aux Pays-Bas.

Emplacement

Ceci est très spécifique aux DateTimeinstances. Une date et une heure représentent un événement à un moment précis, mais celui-ci doit généralement être transmis / présenté à l'utilisateur en fonction de son propre fuseau horaire. Exemple: une DateTimeinstance 2016-09-21T23:38:21.399Zpourrait être affichée comme 9/21/2016 5:21 PMpour un utilisateur du fuseau horaire oriental aux États-Unis. Il existe de nombreuses façons d’y parvenir, mais cela devient pratiquement impossible si l’instance d’heure de la date est conservée en mémoire en tant que type de chaîne ou dans le magasin de données en tant que type de chaîne.


Règle générale

Les 2 règles générales pour une application suivent lorsqu’il s’agit de convertir un type primitif en représentation sous forme de chaîne sont les suivantes:

  • Lors de l'acceptation d'une entrée, convertissez cette entrée dans le type de primitive correct le plus tôt possible dans la pile de programmes (généralement dans la couche de présentation).
  • Lors de la récupération des données à afficher, convertissez ces données en représentation sous forme de chaîne aussi tard que possible dans la pile de programmes (à nouveau, généralement dans la couche de présentation).
Igor
la source
0

Il n’ya vraiment rien de mal à faire cela (c’est tout le temps dans les services) tant que vous utilisez un format non ambigu pour votre date. Par sans ambiguïté, je veux dire non seulement la date est claire (par exemple, MM / JJ ou JJ / MM), mais aussi le fuseau horaire dans lequel elle se trouve. Donc, si vous allez représenter vos dates sous forme de texte, utilisez un format ISO. . Je préfère fortement les chaînes de temps UTC.

Avantages:

  • Date et heure basées sur des normes Les chaînes sont portables et faciles à comprendre
  • Les dates dans les bases de données contiennent souvent un composant heure. Si cela n’a pas de sens pour vos données, cela peut réellement simplifier les choses.

Les inconvénients:

  • Taille des données Le format interne d'une date dans une base de données utilisera généralement beaucoup moins d'espace que le rendu sous forme de chaîne de cette date.
  • Vous allez généralement vouloir l'inscrire dans une structure de date ou d'heure réelle sur le client afin que le temps d'analyse puisse être plus long.

Si quelqu'un disait qu'il voulait faire cela, je demanderais "pourquoi?" parce qu'il n'y a pas vraiment beaucoup de point à cela. Si la raison pour laquelle une personne souhaite renvoyer la date sous forme de chaîne est simplement affichée directement, ce n'est pas une bonne raison d'utiliser des chaînes à partir de la base de données.

JimmyJames
la source