web-dev-qa-db-fra.com

Pourquoi n'y a-t-il pas un type de données pour une seule date?

L'une des premières choses que j'ai apprises sur les dates et les heures en c # (et diverses autres langues) est qu'une date est stockée en tant que DateTime avec le composant time réglé sur minuit. Il n'y a pas de différence entre "1er janvier 2017" et "1er janvier 2017 00: 00: 00.000". Si vous devez afficher uniquement une date, vous pouvez utiliser des fonctions de mise en forme comme ToString pour supprimer la partie heure.

Cela semble causer beaucoup de problèmes, dont quelques-uns que je vais énumérer ici:

  1. DateTime occupe plus d'espace de stockage que nécessaire: 8 octets au lieu des 3 requis pour une date simple.

  2. L'utilisation de 00:00:00 pour "aucune date" confond "une valeur connue de 0" avec une "valeur inconnue". Cela semble plutôt noble, de la même manière qu'un nouveau programmeur pourrait confondre une chaîne nulle avec une chaîne vide. Nul et vide sont différents, et "pas de temps" et "minuit" sont des idées différentes.

  3. Vous voyez des idiomes comme celui-ci apparaître, même dans des comparaisons relativement simples:

    if (startDate >= myDateTime && myDateTime < endDate.AddDays(1))
    

    ou

    if (startDateTime >= myDate && myDate <= endDateTime.Date)
    

    au lieu d'un beaucoup plus simple

    if (startDate >= myDate && myDate <= endDate)
    
  4. Lorsque des composants système situés dans des fuseaux horaires différents s'appellent via des services Web et que le schéma de ces services Web est généré à partir de types C #, un élément d'heure peut être introduit (afin que la date résultante se produise tôt le matin) ou la date la valeur peut en fait changer d'un jour (par exemple, la date finale est en fait la veille à une heure tard dans la soirée). Cela peut rendre difficile la transmission de valeurs agnostiques par rapport au fuseau horaire, par ex. une date de naissance ou une date d'expiration de carte de crédit.

SQL Server a un type Date qui stocke uniquement le mois, le jour et l'année.

XSD spécifie différents types de données pour Date, Time et DateTime.

Pourquoi c # n'a-t-il pas un tel type?

Comment y travaillez-vous? Par exemple, les propriétés c # peuvent-elles être attribuées afin qu'elles soient sérialisées en tant que date au lieu de date/heure?

9
John Wu

Qu'est-ce qu'une date?

Disons qu'il est midi dans votre région. Vous regarderez votre horloge et verrez quelque chose comme 22/03/2017 12:00. On pourrait facilement dire que c'est la date actuelle pour tout le monde dans le monde, non?

Eh bien pas vraiment. Si vous êtes à Londres ou, disons, en Russie ou aux États-Unis, votre horloge n'est pas vraiment correcte en ce qui concerne ces endroits. Votre horloge indique le mauvais moment pour le reste du monde, et pour certains endroits, même la mauvaise date. Lorsque vous parlez du "monde", avoir un rendez-vous sans heure n'a guère de sens une fois que vous commencez à considérer des personnes en dehors de votre fuseau horaire. Pensez à quel point il est ennuyeux d'aller sur un site Web étranger et de voir que, d'une manière ou d'une autre, le contenu généré par l'utilisateur vient du futur. C'est ce qui arrive quand on ne prend pas en compte les fuseaux horaires!

C'est là que C # DateTime entre en jeu.

DateTime n'est pas la date simple habituelle dont vous pourriez avoir besoin pour un logiciel local, juste pour mon entreprise. Il s'agit d'une structure de données quelque peu puissante qui avait l'intention de pouvoir fournir le temps coordonné universel à n'importe quelle application. La partie magique de la structure DateTime est que, avec des manipulations mineures, vous pouvez lui faire afficher le DateTime correct pour chaque endroit dans le monde.

L'idée derrière DateTime était de fournir non pas un simple objet Date, mais quelque chose que vous pourriez utiliser pour représenter des dates partout dans le monde, même avec différents fuseaux horaires. Il a été conçu dans des applications globales et a donc été conçu avec un tas de fonctionnalités supplémentaires qui peuvent ne pas avoir d'utilité apparente à première vue, mais qui peuvent néanmoins économiser beaucoup de temps aux personnes développant des applications qui devront gérer des fuseaux horaires variables. .

Il est loin d'être parfait, oui, mais il fait ce à quoi il était destiné - représenter le Temps de manière universelle et quelque peu portable.

Donc, dans un sens, lorsque vous utilisez C #, vous êtes obligé de prendre en compte les moments lors du développement de votre application, pas seulement les dates. Et, vraiment, c'est une bonne chose - un DateTime est un point de référence dans le temps par rapport à quelque chose, et lorsque vous changez votre point de référence, la valeur de ce DateTime doit agir en conséquence.

Pour être tout à fait juste, je pense que C # est l'un des langages qui a bien fait les choses. Vous pouvez avoir un intervalle de temps sans date (TimeSpan est là pour ça), mais vous ne pouvez pas vraiment avoir une date significative sur une portée globale sans un cadre de référence et une heure qui lui est attachée. Je n'aimais pas du tout DateTime lorsque j'ai rencontré le langage pour la première fois, mais après avoir dû développer une application avec plusieurs fuseaux horaires, j'ai compris pourquoi ce choix de conception était en fait intelligent.

16
T. Sar

Anthony Moore fournit ne entrée de blog avec des notes historiques spécifiquement sur DateTime , y compris une discussion sur les types de problèmes que Microsoft tentait de résoudre. C'est un peu vieux, mais ça donne quand même un aperçu.

La plupart de l'article est consacré au traitement des problèmes de fuseau horaire et des problèmes de compatibilité descendante. Il apparaît que tout au long de l'histoire des versions .NET, Microsoft s'est rendu compte que l'espace des problèmes est très complexe et que tout ce qu'ils ont fait semble être le résultat d'un désir de compromis entre la richesse des fonctionnalités et la simplicité. Voici un extrait intéressant qui semble évoquer (très brièvement) le problème d'une représentation date uniquement:

Tout d'abord, considérez le paysage des scénarios liés à la date et à l'heure:

A. Legacy DateTime Interop (bases de données, COM, Win32, etc.).

B. Scénarios DateTime abstraits (par exemple, heure de début du magasin).

C. Scénarios de date uniquement.

D. Scénarios temporels.

E. Scénarios de temps absolus. (par exemple, l'heure du fichier).

F. Scénarios de serveur avec des dates de plusieurs fuseaux horaires où l'heure locale d'origine doit être conservée.

Les scénarios C-D pourraient être encore mieux gérés par des types de date et d'heure dédiés. Ces options sont toujours sur la table, bien qu'elles ne seront pas dans la version .NET 3.5.

Il semble donc qu'ils l'ont fait envisagent un type de données Date et il était toujours sur la table lorsque ce blog a été écrit. Un peu plus d'explications peuvent être trouvées ailleurs dans l'article:

Il y avait beaucoup de désir de garder le système de type simple, et bien qu'un DateTime connaissant le fuseau horaire soit mieux à représenter des points absolus dans le temps, comme un horodatage de fichier, il est devenu gênant lorsque vous faites certaines choses .... Représenter des dates entières , par exemple le type de retour d'un contrôle de calendrier. Évidemment, un type "Date" est une meilleure façon de représenter cela, et beaucoup de gens ont demandé des types Date et Heure séparés, mais dans la V1.0, il y avait un désir de garder le nombre de types de base petits pour limiter la complexité de la plate-forme. Cette demande de fonctionnalité est certainement toujours sur la table, bien que non prévue pour .NET 3.5

Je pense donc que la réponse est ... oui, ils y ont pensé ... non, ils ne l'ont pas encore fait, car cela pose certains problèmes et il y a un désir de garder la plate-forme globale simple.

Pendant ce temps, ils ont publié la nouvelle structure DateTimeOffset , qui résout certains des problèmes de fuseau horaire. Mais pas de problème de date uniquement. Espérons que les problèmes de date seulement seront examinés ensuite.

3
John Wu

Il n'y a pas une telle classe dans les bibliothèques standard CLR, mais il y a souvent un besoin d'une telle chose, pour les raisons que vous avez identifiées et d'autres.

Vous pouvez importer la bibliothèque "Noda" pour C # et utiliser LocalDate pour représenter une date sans heure spécifique.

Cette classe est basée sur une classe similaire de la bibliothèque Java "Joda", qui s'est avérée si utile et bien écrite qu'elle a maintenant été importée dans le Java bibliothèques standard: LocalDate

Lors de la conversion d'un LocalDate (sans heure) en un DateTime standard (avec un composant temps), la bibliothèque vous oblige à rendre vos hypothèses explicites, ce qui évite toutes sortes de cas Edge et les erreurs que vous avez identifiées dans votre question et dans la discussion sur la réponse de T. Sar

3
Rich