Pourquoi n'y a-t-il pas un véritable type de données «Date uniquement»?

24

Je suis tellement ridiculement frustré de devoir utiliser des valeurs DateTime pour des ensembles de données qui ne sont «qu'une journée». Les anniversaires sont l'exemple le plus courant, mais cela revient tout le temps dans les applications d'entreprise.

Je me suis habitué à simplement régler la partie Heure des enregistrements "date uniquement" sur "midi" (ce qui évite que la date ne change jamais, quel que soit le fuseau horaire). Cela semble être un piratage, et je trouve toujours des bugs de développeurs juniors qui se déplacent sur ce problème.

Le temps est toujours relatif à un point fixe. 16 heures est 4 heures après le méridien, ou midi. Le point de transit le plus élevé du soleil est observable et nous permet de mettre en place un système de coordonnées. 3 heures avant midi (Ante Meridian), 2 heures après midi, 1441899402938 millisecondes depuis le 1er janvier 1970. Pour les personnes élevées dans un monde cartésien, c'est une seconde nature.

Mais notre calendrier est antérieur à Descartes. Mon argument est qu'il est plus correctement considéré comme une énumération sur laquelle une fonction modulo est appliquée. Le lundi suit le dimanche, et ainsi de suite jusqu'à ce que vous arriviez au fait que le dimanche suit le samedi. Il n'y a ni positif ni négatif, c'est un module, ou une valeur absolue.

De même avec des années se répétant. Tous les 365 jours (environ), il y a plusieurs jours spéciaux pour moi: les anniversaires, les anniversaires, les anniversaires des enfants, etc. nous POUVONS mapper cela sur un nombre à virgule flottante, et en vérité, le mapper sur ledit nombre résout BEAUCOUP de problèmes qui sont vraiment difficiles à l'ancienne, mais cela ne signifie pas que c'est la seule façon de le faire.

La connaissance et la compréhension de la nature de la «cheville carrée dans un trou rond» de l'utilisation de DateTimes pour stocker des dates font de moi un meilleur programmeur.

Y a-t-il une valeur dans une application explicitement conçue comme une application de planification dans la définition d'une classe Date, ou est-ce que "régler toutes les heures sur midi" est la meilleure approche? Quels problèmes peut-il y avoir avec l'utilisation de DateTime et la définition du composant Time sur Noon? Le décalage de fuseau horaire peut-il être pris en compte dans une telle approche? J'ai utilisé MomentJS, mais je pense que c'est juste une meilleure classe Date.

Michael Blackburn
la source
7
c'est une question assez intéressante, je pense. Prenons l'exemple de l'anniversaire, cela n'a vraiment de sens que chez l'homme, je vis au même endroit et tout le monde se réveille en même temps, en quelque sorte. dès que vous devez l'exprimer mathématiquement, cela devient très complexe. Même chose avec des choses comme les heures de début et de fin du quart de travail, etc., elles ne sont pas des «heures», ce sont des «heures de la journée dans le fuseau horaire dans lequel vous travaillez»
Ewan
3
NodaTime (une bibliothèque C # pour la date et l'heure) a un type de dates.
CodesInChaos
5
Stockez vos heures en UTC, pas de problème de date, pas de problème de fuseau horaire.
Loren Pechtel
3
"Mais Dieu, cela semble être un hack, et je trouve toujours des bugs de développeurs juniors qui trébuchent sur ce problème." - pourquoi ne pas simplement créer votre propre classe DateOnly ou autre et l'appeler un jour.
Brandin
5
@MichaelBlackburn Je suis sérieux. Votre explication résume exactement la situation pour un type de données propre qui applique la règle métier (date uniquement, par exemple, vous pouvez la stocker en tant que "DateTime" en interne avec la partie heure définie sur midi), mais ensuite exposez uniquement les parties que vous souhaitez (mois , jour etc. année / sans année).
Brandin

Réponses:

15

Tout d'abord, éliminons une chose: les anniversaires sont une chose, les dates de naissance en sont une autre. Un anniversaire est un type de données exotique car il lui manque non seulement les composants des heures, des minutes, etc. mais il lui manque également le composant de l'année. Si vous voulez vraiment gérer les anniversaires, je vous recommande d'inventer votre propre type de données qui ne contient qu'un numéro de mois et un numéro de jour, et qui n'est lié à aucun des types de données date-heure intégrés.

D'un autre côté, si vous voulez aussi garder une trace de l'année de naissance, alors ce que vous avez n'est pas des anniversaires, ce sont des dates de naissance . Donc, la question devient maintenant pourquoi n'y a-t-il pas de type de données uniquement pour la date, afin que vous puissiez facilement représenter les dates de naissance, et que les langues populaires semblent plutôt vous obliger à utiliser un type qui inclut également un composant de temps.

Permettez-moi de mentionner brièvement qu'il n'est pas vrai que tous les langages de programmation n'offrent que des types de données temporelles qui incluent une composante temporelle. J'ai rencontré des types de données à date uniquement dans les SGBDR et dans leurs dialectes SQL correspondants. Mais ce n'est pas pertinent: le fait que ces types de données existent ne signifie pas qu'ils sont une bonne chose à avoir, et les SGBDR ont une longue histoire de confusion entre stockage et représentation.

Vous comprendrez pourquoi c'est une mauvaise idée d'avoir de tels types de données date seulement au moment où vous réalisez que le temps est une coordonnée. La plupart des gens ont une idée très vague de ce qu'est le temps, et cette idée contient des notions culturelles mystérieuses telles que les années, les mois et les jours, sans se rendre compte que ces notions sont exclusivement figuratives : elles ne sont utiles que pour représenter le temps à un humain et pour recevoir le temps comme entrée d'un humain. À n'importe quelle couche en dessous du contrôle GUI d'entrée de temps réel, le temps doit être, et est généralement, représenté comme une coordonnée de temps, qui est un nombre unique d'unités de temps depuis une certaine origine.

Par exemple, dans le DateTimetype de données de Microsoft Dotnet, l'unité de temps est de 100 nanosecondes et l'origine de l'heure est 12:00 minuit, le 1er janvier 0001 CE

Un autre exemple de notation arcane, exclusivement figurative, est la mesure d'angle en degrés, minutes d'un degré et secondes de degré. Bien sûr, pour effectuer tout calcul utile, vous devez utiliser en interne les radians et, si nécessaire, convertir en degrés et en degrés lorsque vous interagissez avec un utilisateur humain.

Donc, ne confondez pas la représentation lisible par l'homme d'une mesure avec la nature réelle de la mesure. Très souvent, la méthode idéale pour réaliser une mesure, qui correspond le mieux à la nature de la mesure, est très différente de la représentation lisible par l'homme de cette mesure.

À la lumière de tout cela, votre demande pour un type de données temporelles qui ne représente que des dates s'apparente à une demande pour un type de données angulaire qui ne serait capable de représenter que des degrés, empêchant explicitement une plus grande précision. Un tel type de données serait assez limité, et finalement inutile, car vous devriez quand même le convertir vers et depuis des radians afin de faire quoi que ce soit d'utile.

Votre problème avec la date de naissance est que vous avez une coordonnée de temps imprécise : la personne est, bien sûr, née à un moment précis, mais l'heure et la minute n'ont pas été enregistrées par l'hôpital, ou nous ne le faisons pas se soucient d'eux. Donc, ce qui se passe vraiment, c'est que votre coordonnée de date et d'heure de naissance a une marge d'erreur, une tolérance ou une incertitude si vous le souhaitez, et il est préférable de la traiter comme telle: mettez-la exactement au milieu de la journée, et considérons une incertitude implicite de +12-12 heures. Et c'est précisément la solution à laquelle vous êtes intuitivement arrivé.

Mike Nakis
la source
4
Ce n'est pas vrai pour les "jours" qui sont un concept encore plus ancien que le temps. Ils sont considérés à juste titre comme une énumération ou un module. Le dimanche suit le lundi, etc. jusqu'à ce que nous revenions au dimanche, qui suit le samedi. C'est vraiment quelque chose de différent.
Michael Blackburn,
10
Bien sûr, l'hôpital a noté l'heure de naissance - c'est la pratique courante dans la plupart des hôpitaux. Ce n'est pas du tout le problème. Le problème est que pour commémorer des événements (anniversaires, jours fériés, anniversaires, etc.), les gens n'utilisent pas ou ne veulent pas de résolution plus fine que 1 jour. Allez demander à la première personne que vous voyez quand son anniversaire aura lieu, et ils vous donneront un mois et un jour, mais jamais une heure et une minute. Aussi: nous utilisons des unités qui incluent l'échelle tout le temps: millimètre, kilogramme, mégawatt et même microfarad.
Caleb
4
-1: Toutes les utilisations du temps ne doivent pas représenter un seul instant dans le temps. Un anniversaire est une idée différente, représentée par un mois et un jour dans le calendrier grégorien. Il est logique de demander "est-ce l'anniversaire de Kevin aujourd'hui?" La réponse dépend de l'emplacement. Si je suis à Sydney, ce pourrait être mon anniversaire, mais si j'étais à Honolulu à la place, ce ne serait pas encore pour quelques heures.
kevin cline du
6
@MikeNakis Le résultat serait des microampères, pas des bêtises. Plus important: lorsque vous utilisez une date plutôt qu'une seconde ou une milliseconde, vous parlez généralement de la journée entière - une période de temps - plutôt qu'une heure spécifique, et selon le contexte, il peut s'agir d'un événement récurrent.
Caleb
4
L'OP parlait des anniversaires, qui sont exactement représentés par java.util.MonthDay. Un anniversaire n'est pas une mesure, c'est la notion humaine d'un jour qui se répète chaque année. Il y a beaucoup d'idées humaines du temps qui ne sont pas représentées par un seul point dans le temps.
Kevin Cline du
9

Les dates et les heures sont différentes en fonction du contexte et vous avez besoin de plusieurs types distincts pour couvrir tous les cas d'utilisation.

Le DateTimetype présent dans de nombreuses langues représente un moment précis dans le temps ("instantané"). Au-delà de cela, nous avons un certain nombre de concepts de temps et d'intervalle de temps relatifs ou "humains" comme les jours civils, les dates récurrentes, les mois, les années, etc. qui sont dans de nombreux cas ambigus et dépendent du contexte. Ces types ne sont pas aussi universellement utiles, mais nécessaires dans des domaines d'application spécifiques comme les calendriers, les outils de planification et d'autres applications qui interagissent avec les concepts humains du temps.

Si vous écrivez quelque chose comme une application de calendrier, vous bénéficierez certainement d'utiliser une bibliothèque comme Joda-time qui fournit un ensemble plus riche de types de temps. Par exemple LocalDate, une date sans heure. Cela a une sémantique différente de l'ordinaire DateTimeavec la partie de temps définie sur zéro, car le DateTimeindique toujours un moment précis (minuit dans un fuseau horaire spécifique), tandis LocalDatequ'indique toute la journée et n'est pas lié à un fuseau horaire spécifique. Cela signifie également que vous ne pouvez pas traduire directement l'un en l'autre.

LocalDateest certainement plus simple que DateTimeparce qu'il n'a pas à prendre en compte les fuseaux horaires, mais vous devez être conscient des autres problèmes, par exemple que la date actuelle peut en fait reculer lorsque vous traversez un fuseau horaire, et que le même instant dans le temps peut correspondent à différentes dates dans différents fuseaux horaires. Si vous utilisez des dates locales dans des applications Web ou en réseau, vous devez faire très attention à ces problèmes. La suppression de la partie horaire d'une date ne résout pas le problème fondamental des fuseaux horaires! Et si vous prenez en considération les dates historiques et les différentes cultures, cela devient encore plus difficile, car la même date peut correspondre à des moments extrêmement différents dans le temps, par exemple le calendrier julien contre le calendrier grégorien.

Vous demandez maintenant pourquoi les langues n'ont pas quelque chose comme LocalDate intégré . Eh bien tout d'abord, certains langages comme SQL et Visual Basic ont un type de date sans partie d'heure. Et Java a également ajouté un LocalDatedans la version récente. Mais d'autres plateformes comme .Net ne le font pas. Seuls les concepteurs de langage peuvent vraiment expliquer pourquoi cela n'est pas inclus dans la bibliothèque standard, mais je suppose que le "temps instantané" est conceptuellement simple et universellement utile, tandis que les autres concepts de temps ne sont utiles que pour des domaines d'application spécifiques (comme les calendriers, etc. .). Il est donc logique de laisser le développeur de l'application écrire des types personnalisés pour gérer les cas d'utilisation plus complexes, ou de le laisser être géré par une bibliothèque tierce (comme Joda-time).

JacquesB
la source
5

Je suis tellement ridiculement frustré de devoir utiliser des valeurs DateTime pour des ensembles de données qui ne sont «qu'une journée». Les anniversaires sont l'exemple le plus courant, mais cela revient tout le temps dans les applications d'entreprise.

Cela est probablement dû au fait que les calendriers sont compliqués et utilisés de tant de façons différentes que personne n'a pu comprendre une classe qui soit simple mais suffisamment générale pour être utile dans de nombreux domaines.

Le type de date communément trouvé dans les langages de programmation peut être utilisé pour dater avec précision les transactions dans un système informatique. D'autres cas d'utilisation nécessiteront probablement une bibliothèque personnalisée.

Voici une courte liste de faits sur les calendriers, démontrant leur complexité - la plupart d'entre eux sont historiques, donc si vous limitez votre attention aux dates après le 1.1.1970, cela ne vous affectera pas. Cependant, si votre application doit fonctionner avec des dates antérieures à la fin du 19e siècle, ces faits importent. Les cas d'utilisation possibles sont des bases de données historiques de toutes sortes (livres, généalogie) mais aussi des actifs de grandes entreprises ou organisations encore en activité aujourd'hui.

Tous ces faits sont extraits de l'excellente FAQ de la bibliothèque de calendriers pour OCaml écrite par Julien Signolles.

  1. Le calendrier julien a été introduit par Jules César en 45 avant JC. Il était d'usage courant jusqu'aux années 1500, lorsque les pays ont commencé à passer au calendrier grégorien (section 2.2). Cependant, certains pays (par exemple, la Grèce et la Russie) l'ont utilisé dans les années 1900, et l'église orthodoxe de Russie l'utilise toujours, comme le font d'autres églises orthodoxes.

  2. Le passage du calendrier julien au calendrier grégorien ne s'est pas produit de manière uniforme, et selon l'année de changement, 10 à 13 jours ont été abandonnés. Par exemple, en France, le 9 décembre 1582 a été suivi du 20 décembre 1582 et en Grèce, le 9 mars 1924 a été suivi du 23 mars 1924.

  3. Même à l'ère moderne, de nombreux calendriers différents sont utilisés (grégorien, orthodoxe, islamique et chinois) pour en citer quelques-uns, qui utilisent tous différentes manières de calculer les années et les anniversaires ou la date des célébrations religieuses.

Vous espérez maintenant un type de date regroupé avec des opérations utiles pour les opérations commerciales générales. Je suppose que les opérations commerciales générales n'existent pas. Par exemple, dans le monde de la finance, nous devons calculer:

  1. Les fractions annuelles (comme «6 mois» correspond à «0,5»), qui sont utilisées conjointement avec un taux d'intérêt pour calculer les intérêts réels sur un prêt pour une durée donnée. Il y a 6 à 10 recettes pour calculer ces fractions, chacune différant par la façon dont elles gèrent la durée d'une année bissextile, la position de la période par rapport au dernier jour de février et la durée d'un mois.

  2. Lors du calcul de la date, lors du calcul des anniversaires, nous utilisons un calendrier et une règle (choisis parmi un ensemble de plus de 6 règles différentes) pour déplacer un anniversaire d'un jour férié à un jour ouvrable.

Pour les personnes travaillant dans le secteur financier, tout type de calendrier ne mettant pas en œuvre toutes ces fonctions et règles est inutile. Il est probable que de nombreuses autres industries ont d'autres types d'habitudes et de conventions nécessitant des calculs personnalisés sur le calendrier.

Y a-t-il une valeur dans une application explicitement conçue comme une application de planification dans la définition d'une classe Date, ou est-ce que "régler toutes les heures sur midi" est la meilleure approche? Quels problèmes peut-il y avoir avec l'utilisation de DateTime et la définition du composant Time sur Noon? Le décalage de fuseau horaire peut-il être pris en compte dans une telle approche? J'ai utilisé MomentJS, mais je pense que c'est juste une meilleure classe Date.

Si vous devez garder une trace d'un seul jour civil, le meilleur moyen est probablement d'utiliser un grand entier représentant le jour julien de ce jour civil. Les algorithmes de conversion aller-retour du jour julien au jour calendaire - décrits avec l'année, le mois et le calendrier - sont largement connus et testés de manière approfondie, afin que vous puissiez les implémenter facilement dans votre application - et déterminer quelle règle est pertinente dans votre cas pour calculer l'anniversaire d'un événement survenu le 29 février.

Michael Le Barbier Grünewald
la source
2

Je pense que Mike Nakis dans sa réponse ci-dessus fait un meilleur travail que moi pour expliquer comment le temps en général est une coordonnée mesurée absolue et toute autre communication, état supposé ou persistance de cette coordonnée temporelle n'est qu'une représentation abstraite de ladite coordonnée temporelle.

Vous parlez de telles représentations lorsque vous vous référez au Jour de la Semaine comme étant simplement une sorte de module de représentation d'un moment réel. En réalité, c'est un peu plus compliqué que cela. Si vous avez été chargé d'écrire une fonction qui renverra le jour de la semaine pour un moment donné, considérez les informations suivantes dont vous aurez besoin comme entrée d'un tel algorithme. Vous aurez besoin du point dans le temps, du calendrier, du fuseau horaire à prendre en compte (gardez à l'esprit, les fuseaux horaires changent TOUT LE TEMPS donc vous devez savoir quand ce fuseau horaire effectif a commencé à se terminer en coordonnées horaires spécifiques. La Corée du Nord a récemment changé la leur par exemple!), et si l'heure d'été est en vigueur, cela change aussi avec le temps. Considérez maintenant si vous avez reçu un DateTime dans le fuseau horaire local,

Vous pouvez voir à quel point cette question apparemment simple peut être compliquée.

Je connais la douleur que vous ressentez lorsque j'étais à votre place à un moment donné, corrigeant tous les bogues dans une application de planification des visites pour un produit écrit par des développeurs inexpérimentés. Le tout a dû être abandonné.

Le temps est en effet une coordonnée, mais en plus d'une simple date, considérez d'autres données sensibles au temps qui pourraient être nécessaires comme:

Durée: un intervalle de millisecondes qui peut se produire et qui signifie une durée ou un passage de temps sans coordonnées temporelles spécifiques spécifiées. Un cas d'utilisation pourrait être,

En tant qu'utilisateur, j'aimerais que cette tâche soit effectuée 15 secondes après la fin du travail de minuit tous les deux mercredis.

Intervalle: une plage de temps entre deux coordonnées temporelles spécifiques. Un cas d'utilisation où vous pouvez envisager un intervalle.

En tant qu'utilisateur, je dois voir chaque jour du mois entièrement contenu dans un intervalle de temps spécifié.

Un autre point rapide que je voulais faire est que vous avez fait un commentaire sur les nombres à virgule flottante pour les données temporelles et je vous le déconseille. L'arithmétique en virgule flottante entraîne inévitablement des erreurs d'arrondi qui peuvent ne pas vous donner une mesure aussi précise que nécessaire pour le temps.

Donc, en conclusion, toutes ces informations conduisent inévitablement aux considérations de conception suivantes:

  • Des points ou des plages de temps spécifiques doivent être conservés en UTC ou dans un type de données contenant suffisamment d'informations pour être facilement résumés en UTC si nécessaire.
  • La logique d'application doit être écrite pour formater UTC ou une plage de coordonnées UTC dans un état de données représentatif plus digestible pour l'utilisateur final.
  • Les durées importantes doivent être conservées en millisecondes
  • Les préférences spécifiques aux paramètres régionaux ou de l'utilisateur final sur l'affichage de toutes les données concernant le temps doivent être conservées en tant que données supplémentaires et traitées comme une option d'affichage. (Par exemple, kiosque A, fuseau horaire central, format d'heure militaire ou préférences de l'utilisateur B, fuseau horaire de Tel Aviv (GMT + 7: 00), etc.)
  • Évitez les numéros FP
maple_shaft
la source
1
Rien de tout cela n'est "inévitable". Il peut être courant pour de nombreuses applications, mais le Grand collisionneur de hadrons traite des événements à l'échelle nanoseconde. Les temps système sont passés aux microsecondes car les millisecondes n'ont pas assez de précision. Les applications de calendrier doivent avoir un concept de date qui se produit un jour de calendrier local, que vous soyez ou non dans le même fuseau horaire que vous avez créé l'événement.
Alan Shutko
1
@AlanShutko Et oui, les "données supplémentaires" nécessaires sont des éléments comme le fuseau horaire local et les jours, ainsi que toute autre donnée importante qui doit être capturée. Ce ne sont cependant que des abstractions à un seul point dans le temps, même si le point dans le temps n'est pas important pour votre algorithme. En ce qui concerne l'échelle nanoseconde et même microseconde, ma réponse est davantage orientée vers les logiciels de type web et LOB. Je doute que le langage LHC de choix soit C # ou Javascript.
maple_shaft
1
Les millisecondes sont idéales pour les processus physiques reproductibles. Pour l'activité humaine, l'unité appropriée est parfois le nombre nominal de jours, par exemple si elle est expédiée à la fin de la journée, elle sera disponible pour être utilisée à destination trois jours plus tard.
kevin Cline
Dans le passé, j'ai envisagé d'utiliser des nombres à virgule flottante 64 bits pour les coordonnées temporelles, et surtout pour les intervalles de temps, car ils vous permettent d'exprimer de petites quantités avec une grande précision, ainsi que d'énormes quantités, où la perte de précision n'a pas vraiment d'importance . (Et si les dinosaures sont morts il y a 65 millions d'années, donnez ou prenez quelques années?) Alors, pourquoi dites-vous qu'ils devraient être évités?
Mike Nakis du
Mike, je pense que sa préoccupation concerne les mathématiques FP, qui sont inévitablement arrondies lors de la conversion des valeurs décimales en valeurs binaires. Par exemple, 0,3 est une décimale répétitive lorsqu'elle est exprimée sous la forme d'un nombre binaire FP, et ne peut donc pas être représentée exactement. Ce n'est pas que vous manquez la capacité, mais vous manquez la précision.
Michael Blackburn
2

En bref, parce que la plupart des types d'heure sur ordinateur se concentrent sur la gestion correcte du problème d'heure et de fuseau horaire.

Il y a 2 cas marginaux qui ne sont pas bien servis par l'approche habituelle. Définir un point dans le temps qui est de l'autre côté d'un changement d'heure d'été en utilisant l'heure locale, qui est ensuite converti en UTC par une couche d'abstraction inférieure, puis vous fait 1 heure plus tôt / plus tard pour votre réunion.

L'autre consiste (selon la question) à modéliser des informations de date arbitraires, telles que l'enregistrement de la date de naissance d'une personne. Imaginez le cas où deux personnes naissent en même temps, l'une en Nouvelle-Zélande, l'autre à Hawaï. La probabilité est qu'ils auront des dates de naissance différentes sur leur passeport, et si la personne née à Hawaï déménage en Nouvelle-Zélande, elle sera considérée comme un jour plus âgée que la personne née en Nouvelle-Zélande, bien qu'elle ait vécu exactement à la même époque.

La suggestion dans la question comme fixer la date pour avoir une heure de midi, UTC fonctionnera, PRESQUE partout. Les décalages UTC vont de -12 à +14, il y a donc quelques endroits dans le Pacifique où cette approche échouera. J'ai tendance à traiter ces types de données comme des chaînes, au format aaaammjj, et si je dois faire des calculs de comparaison entre deux dates, cela peut être fait en toute sécurité comme comparaison de chaînes. Lorsque vous effectuez des comparaisons delta (par exemple entre la date et maintenant, ou combien de temps jusqu'à ce qu'elles atteignent l'âge X), vous devez vous assurer que toutes les dates sont créées dans le même décalage UTC, et pouvez ensuite utiliser les fonctions d'heure standard pour effectuer le travail.

Michael Shaw
la source
3
«J'ai tendance à traiter ces types de données sous forme de chaînes, dans un format aaaammjj, et si je dois faire des calculs de comparaisons entre deux dates, cela peut être effectué en toute sécurité comme une comparaison de chaîne. » Cela semble sûr comme un Datetype de données, vient d' être transporté dans aString
Ross Patterson
Tout comme vous le dites, c'est une représentation sous forme de chaîne d'une date, et contrairement à l'affiche originale, la date n'est pas modifiée en étant dans un fuseau horaire UTC + 13.
Michael Shaw,
2

Pourquoi n'y a-t-il pas un véritable type de données «Date uniquement»?

Pour les mêmes raisons, je pense, que les valeurs DateTime sont généralement spécifiées en UTC: simplicité et fiabilité . Le point d'une valeur DateTime est de spécifier un seul point dans le temps qui n'est pas affecté par le fuseau horaire, l'heure d'été, le calendrier et d'autres ajustements locaux. Les valeurs DateTime spécifient un instant (jusqu'à la limite de la résolution du type), pas une période ou un ensemble d'heures. Ces limitations permettent de comparer les valeurs DateTime de manière fiable, prévisible et simple.

Essayer de spécifier une date avec une valeur DateTime revient à essayer d'utiliser un point pour spécifier une zone.Vous pouvez faire fonctionner cela en utilisant une convention, comme "ce point représente le centre d'un cercle avec un rayon de 100m", mais il y a beaucoup de problèmes là-bas: tout le monde doit utiliser la même convention, vous devez écrire un tas de prendre en charge le code pour rendre le travail avec le mauvais type moins pénible, et il est à peu près garanti qu'à un moment donné, vous devrez spécifier une zone plus grande ou plus petite que la zone conventionnelle. Il en va de même pour les dates: vous pouvez utiliser `` midi '' comme heure conventionnelle pour spécifier les dates, mais vous entrez ensuite dans les fuseaux horaires parce que les gens s'attendent à spécifier les dates dans leur heure locale plutôt qu'en UTC. Et même si vous trouvez un moyen satisfaisant d'utiliser un DateTime pour spécifier une date, vous aurez besoin de plus d'informations pour savoir s'il s'agit d'une date absolue ou relative: est-ce le 4 juillet, 1776 ou tous les 4 juillet? Et si vous voulez répéter en utilisant une autre période? Et les calendriers ont toutes sortes de problèmes fous: certains mois sont plus longs que d'autres, certaines années sont plus longues que d'autres, certains jours sont encore plus longs que d'autres, et certains calendriers ont des lacunes. Vous ne voudriez pas résoudre ces problèmes uniquement pendant des jours entiers, car les mêmes problèmes surviennent pour des périodes plus courtes: vous aimeriez probablement être en mesure d'écrire du code qui exprime "prendre 1 pilule toutes les 4 heures" aussi facilement que "le le groupe se réunit tous les troisièmes vendredis. "

Donc, il y a beaucoup de complications à travailler avec les dates. Il est relativement (sans jeu de mots) facile de fournir un type qui spécifie un point dans le temps et de travailler avec lui comme vous le feriez pour un nombre, mais extrêmement difficile de fournir un type qui traite de toutes les façons dont les dates sont utilisées.

Comme d'autres l'ont souligné, il existe des langues et des bibliothèques qui fournissent un bon support pour les dates, et c'est souvent une bonne idée de les utiliser étant donné qu'il est assez difficile d'obtenir exactement le code lié à la date.

Caleb
la source
2
"Difficile de fournir un type qui traite de toutes les façons dont les dates sont utilisées." C'est vrai, c'est pourquoi c'est une horrible idée d'essayer de fournir un seul type pour tout faire. Les premières versions de Java ne fournissaient que java.util.Date et le résultat était horrible. Ensuite, ils ont ajouté une hiérarchie java.util.Calendar complexe et cela ne s'est pas beaucoup amélioré.
kevin cline
1
@kevincline Entièrement d'accord. OP n'a pas spécifié de langue, donc je visais la généralité.
Caleb
" Pour les mêmes raisons, je pense, que les valeurs DateTime sont généralement spécifiées en UTC " ... Oh, serait-ce vrai? Nous sommes en 2015, et il y a encore beaucoup de code en cours d'écriture en utilisant le fuseau horaire de l'auteur :-(
Ross Patterson
1
Je me demandais en effet pourquoi il n'y a pas de convention généralement acceptée concernant les dates. Votre «utilisation d'un point pour représenter une zone» résume parfaitement ma frustration.
Michael Blackburn,
2

Pourquoi n'y a-t-il pas un véritable type de données «Date uniquement»?

Il existe de nombreux types de ce type dans diverses bibliothèques pour différentes langues. Il y en a presque certainement pour votre langue actuelle. Le package util Java avait une horrible API pour les calculs de temps, mais l'introduction du package java.time a rendu la vie bien meilleure. Voir java.time.LocalDate, contenant une valeur année-mois-jour, ou java.time.MonthDay, contenant uniquement un mois et un jour.

Kevin Cline
la source
1

La manipulation calendaire est l'un des aspects les moins bien compris de l'informatique. Des livres entiers ont été écrits sur le sujet. @MichealBlackburn a tout à fait raison de demander un type de données à date uniquement, qui ne se résout pas à un point sur une chronologie, sous réserve de réinterprétation. Historiquement, il y a eu des conflits légitimes sur la signification d'une date. Il ne faut pas chercher plus loin que l'adoption du calendrier grégorien pour découvrir à quel point il peut devenir complexe. De plus, les années n'ont pas toujours commencé le 1er janvier, même en Europe occidentale et dans ses colonies ( par exemple , la Grande-Bretagne et l'Amérique britannique ont commencé l'année le 25 mars).

Ross Patterson
la source
1
C'est juste. La FAQ du calendrier que je cite dans ma réponse est une excellente ressource pour découvrir les complexités et les subtilités des manipulations clandar
Michael Le Barbier Grünewald
-2

En réponse à:

Eh bien, je voudrais honnêtement savoir pourquoi presque toutes les langues n'ont qu'un seul type de données pour cela.

La raison la plus courante pourrait être "parce que ce n'est pas nécessaire". Si vous voulez une date qui ne se soucie pas des heures, des minutes, des secondes, etc., alors il vous suffit de l'initialiser comme ceci:

date = new DateTime(year, month, day, 0, 0, 0);

Si vous le souhaitez, vous pouvez étendre DateTime vous-même:

public class Date extends DateTime {
    ...
    public Date(int year, int month, int day) {
        this(year, month, day, 0, 0, 0);
    }
}

Remarque: j'ignore intentionnellement l'heure et le fuseau horaire par défaut. Peu importe ce que vous les définissez, tant qu'ils sont les mêmes pour tous les Dateart. Vous pouvez plaider en faveur de l'UTC. Vous pouvez faire un cas pour utiliser le fuseau horaire dans lequel se trouve votre serveur - de toute façon, je ne pense pas que ce soit important pour représenter une valeur imprécise comme Date. Idem avec l'heure par défaut - vous pouvez le mettre à 0, vous pouvez le faire à midi. Ça n'a pas d'importance. Si Facebook m'envoie une notification d'anniversaire à 00h01 mais que je suis né à 23h59, je m'en fiche vraiment, et je ne serai pas offensé qu'ils aient plus de 12 heures de congé.

Ce qui précède est en Java mais fonctionnerait de manière similaire dans n'importe quel langage avec un DateTimehéritage. Java a en fait de nombreuses façons de résoudre ce problème, et ce qui précède est déconseillé (ils veulent que vous l'utilisiez Calendarmaintenant). Mais comme d' autres affichés dans les commentaires, certaines langues en fait ne fournissent une Dateclasse, sans doute précisément pour cette raison.

Selon toute vraisemblance, chaque Dateimplémentation est probablement juste un wrapper pour le langage DateTimeet elle met à zéro le temps. Sinon, vous auriez besoin d'un code dupliqué pour résoudre des problèmes tels que le nombre de jours entre deux dates / dates, ou si deux Dates sont égaux (qu'en est-il du 29 février et du 1er mars?). Ce genre de choses est généralement résolu en DateTimeclasse. Il est logique de réutiliser le même code pour a Date.

Shaz
la source
4
-1: Utilisez LocalDate si vous voulez seulement l'année + le mois + le jour. L'utilisation de DateTime à cet effet entraînera des bogues lorsqu'un autre programmeur verra DateTime et supposera qu'il représente un moment dans le temps.
kevin cline
@kevincline Je ne pensais pas que c'était nécessaire car cette question était indépendante de la langue. Je pense également qu'il est évident que l'utilisation de code étiqueté «obsolète» est un scénario d'utilisation à vos risques et périls. Plus important encore , je ne ai utilisé que comme un exemple de quelque chose que vous pouvez faire dans un scénario dans lequel une langue ne possède une LocalDateou Dateclasse de type et vous devez « roll-your-own ».
Shaz
1
Mais "il EST nécessaire" pour un code clair, concis et correct impliquant des règles commerciales sur le temps (par opposition au temps physique). si la bibliothèque ne fournit pas de types pour une durée nominale, le programmeur devra les inventer, et la façon de le faire ne commence pas par "DateTime".
Kevin Cline du
@kevincline Je ne vois pas comment le code serait moins clair ou concis. Quelle est la différence du point de vue d'un programmeur entre new Date(2000, 1, 1);et new Date(2000, 1, 1);? Pouvez-vous dire lequel a des heures, des minutes et des secondes vides en dessous? Si vous vous inquiétez de voir apparaître des fonctions supplémentaires (comme setMinutes ()), alors vous pourriez suivre la voie de l' Dateenveloppement DateTimeau lieu d'en hériter, puis vous exposez uniquement setYear, setMonth, setDay, etc. Et ce n'est certainement pas moins correct que le DateTime de la bibliothèque que vous utilisez.
Shaz
Mon expérience est en grande partie C #, qui n'a pas de construction analogue à LocalDate. Nous venons juste de DateTime et de nous embrouiller, apparemment.
Michael Blackburn