Quel est le problème avec l'API Java Date & Time? [fermé]

105

Très souvent, je rencontre des commentaires négatifs sur Java Dateet d'autres classes liées à la date-heure. En tant que développeur .NET, je ne peux pas pleinement (sans les avoir utilisés) comprendre ce qui ne va pas avec eux.

Quelqu'un peut-il faire la lumière là-dessus?

Anton Gogolev
la source

Réponses:

142

Ah, la Dateclasse Java . Peut-être l'un des meilleurs exemples de la façon de ne pas faire quelque chose dans aucune langue, n'importe où. Par où je commence?

La lecture de JavaDoc peut amener à penser que les développeurs ont en fait de bonnes idées. Il parle longuement de la différence entre UTC et GMT , malgré le fait que la différence entre les deux est essentiellement des secondes intercalaires (ce qui se produit assez rarement ).

Cependant, les décisions de conception gaspillent vraiment l'idée d'être une API bien conçue. Voici quelques-unes des erreurs préférées:

  • Bien qu'il ait été conçu dans la dernière décennie du millénaire, il évalue les années à deux chiffres depuis 1900. Il existe littéralement des millions de solutions de contournement faisant 1900+ (ou 1900-) dans le monde Java à la suite de cette décision banale.
  • Les mois sont indexés à zéro, pour répondre au cas spectaculairement inhabituel d'avoir un tableau de mois et de ne pas vivre avec un tableau de treize éléments, le premier contenant un null. En conséquence, nous avons 0..11 (et aujourd'hui le 11ème mois de l'année 109). Il y a un nombre similaire de ++ et - sur les mois pour convertir en chaîne.
  • Ils sont mutables . En conséquence, chaque fois que vous souhaitez donner une date (par exemple, en tant que structure d'instance), vous devez renvoyer un clone de cette date au lieu de l'objet date lui-même (car sinon, les gens peuvent muter votre structure).
  • Le Calendar, conçu pour «réparer» cela, fait en fait les mêmes erreurs. Ils sont toujours mutables.
  • Datereprésente a DateTime, mais pour s'en remettre à ceux de SQL land, il existe une autre sous java.sql.Date- classe , qui représente un seul jour (mais sans fuseau horaire associé).
  • Il n'y a pas de TimeZones associé à a Date, et donc les plages (comme une `` journée entière '') sont souvent représentées comme minuit-minuit (souvent dans un fuseau horaire arbitraire)

Enfin, il convient de noter que les secondes intercalaires se corrigent généralement par rapport à une bonne horloge système qui est mise à jour avec ntp en une heure (voir les liens ci-dessous). La chance qu'un système soit toujours opérationnel lors de l'introduction de deux secondes intercalaires (tous les six mois au minimum, pratiquement toutes les quelques années) est assez improbable, surtout compte tenu du fait que vous devez redéployer de temps en temps de nouvelles versions de votre code . Même l'utilisation d'un langage dynamique qui régénère les classes ou quelque chose comme un moteur WAR polluera l'espace de classe et finira par manquer de permgen.

AlBlue
la source
43

JSR 310 , qui a supplanté les anciennes classes date-heure avec java.time dans Java 8, se justifie dans le JSR d'origine comme suit:

2.5 Quel besoin de la communauté Java sera traité par la spécification proposée?

Actuellement, Java SE dispose de deux API de date et d'heure distinctes: java.util.Date et java.util.Calendar. Les deux API sont systématiquement décrites comme difficiles à utiliser par les développeurs Java sur les blogs et les forums. Notamment, les deux utilisent un index zéro pendant des mois, ce qui est à l'origine de nombreux bugs. Calendar a également souffert de nombreux bogues et problèmes de performances au fil des ans, principalement en raison du stockage de son état de deux manières différentes en interne.

Un bogue classique (4639407) empêchait la création de certaines dates dans un objet Calendar. Une séquence de code pourrait être écrite qui pourrait créer une date dans certaines années mais pas dans d'autres, ayant pour effet d'empêcher certains utilisateurs d'entrer leurs dates de naissance correctes. Cela était dû au fait que la classe Calendar n'autorisait qu'un gain d'heure d'été d'une heure en été, alors qu'historiquement, il était de plus de 2 heures au moment de la seconde guerre mondiale. Bien que ce bogue soit maintenant corrigé, si à un moment donné dans le futur un pays choisissait d'introduire un gain d'heure d'été de plus trois heures en été, alors la classe Calendar serait à nouveau interrompue.

L'API Java SE actuelle souffre également dans les environnements multithreads. Les classes immuables sont connues pour être intrinsèquement thread-safe car leur état ne peut pas changer. Cependant, la date et le calendrier sont mutables, ce qui oblige les programmeurs à envisager explicitement le clonage et le threading. En outre, le manque de sécurité des threads dans DateTimeFormat n'est pas largement connu et a été la cause de nombreux problèmes de threads difficiles à détecter.

Outre les problèmes avec les classes que Java SE a pour datetime, il n'a pas de classes pour modéliser d'autres concepts. Les dates ou heures, durées, périodes et intervalles hors fuseau horaire n'ont pas de représentation de classe dans Java SE. En conséquence, les développeurs utilisent fréquemment un int pour représenter une durée, avec javadoc spécifiant l'unité.

L'absence d'un modèle complet de date et d'heure rend également de nombreuses opérations courantes plus délicates qu'elles ne devraient l'être. Par exemple, calculer le nombre de jours entre deux dates est un problème particulièrement difficile à l'heure actuelle.

Ce JSR abordera le problème d'un modèle complet de date et d'heure, y compris les dates et heures (avec et sans fuseaux horaires), les durées et périodes de temps, les intervalles, le formatage et l'analyse.

meriton
la source
28
  • Les instances de date sont modifiables , ce qui est presque toujours peu pratique.
  • Ils ont une double nature. Ils représentent à la fois un horodatage et une date du calendrier. Il s'avère que cela pose problème lors des calculs sur les dates.
  • Les représentations numériques des données de calendrier sont contre-intuitives dans de nombreux cas. Par exemple: getMonth()est basé sur zéro, getYear()est basé sur 1900 (c'est-à-dire que l'année 2009 est représentée par 109).
  • Il leur manque beaucoup de fonctionnalités que vous attendez d'une Dateclasse.
jaseur
la source
13

Je ressens pour vous ... en tant qu'ancien programmeur .NET, j'ai posé les mêmes questions, l'API de temps en .NET (délais, surcharge d'opérateurs) est très pratique.

Tout d'abord, pour créer une date spécifique, vous utilisez soit une API obsolète, soit:

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

Pour soustraire un jour, vous faites des choses mauvaises comme

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

ou pire

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

Pour savoir combien de temps s'est écoulé entre deux dates (en jours / semaines / mois) ... c'est encore pire

Cependant, DateUtils d'apache ( org.apache.commons.lang.time.DateUtils) offre des méthodes pratiques et je me suis retrouvé à les utiliser uniquement ces derniers temps

Comme l'a écrit Brabster, Joda Time est aussi une bonne bibliothèque externe, mais Apache semble plus "commun" qu'autre chose ...

Eran Medan
la source
S'il vous plaît, montrez-nous comment faire ("découvrez combien de temps s'est écoulé entre deux dates")!
Anton Gogolev
J'aurais aimé connaître un moyen facile ... y compris les années bissextiles, les mois nerveux et les jours vlolatile ...
Eran Medan
1
Voir aussi, org.apache.commons.lang.time: commons.apache.org/lang//api/org/apache/commons/lang/time/...
trashgod
@AntonGogolev Dans java.time , utilisez Periodet Durationclasses pour calculer et représenter le temps écoulé sur une échelle d'années-mois-jours et heures-minutes-secondes respectivement.
Basil Bourque le
4

Je trouve que l'API Date de Java est utilisable, pour être honnête. La plupart des questions que j'ai vu et entendu à propos se rapportent à la verbosité, la nécessité d'impliquer plusieurs classes pour faire quelque chose d' utile ( Calendar, Date, DateFormat/ SimpleDateFormat) et le manque de accesseurs simples comme getDayOfWeek().

Joda Time est une API alternative très respectée en Java, et dans la section Why Joda Time, elle donne quelques arguments supplémentaires pour expliquer pourquoi c'est une alternative viable qui pourrait être intéressante.

brabster
la source