Date et calendrier Java


364

Quelqu'un pourrait-il s'il vous plaît conseiller les "meilleures pratiques" actuelles Dateet les Calendartypes?

Lors de l' écriture du nouveau code, est - il préférable de favoriser toujours Calendarplus Date, ou y at - il des circonstances où Dateest le type de données plus approprié?



2
Pour votre information, les classes date de temps anciens gênants tels que java.util.Date, java.util.Calendaret java.text.SimpleDateFormatsont maintenant héritage, supplanté par les java.time classes. Une grande partie de la fonctionnalité java.time est rétroportée vers Java 6 et Java 7 dans le projet ThreeTen-Backport . Adapté davantage pour les versions antérieures d'Android dans le projet ThreeTenABP . Voir Comment utiliser ThreeTenABP… .
Basil Bourque

2
Pour info, le projet Joda-Time (mentionné dans un autre commentaire) est désormais en mode maintenance , l'équipe conseillant la migration vers les classes java.time . Voir Tutoriel par Oracle .
Basil Bourque

Réponses:


377

La date est une classe plus simple et est principalement présente pour des raisons de compatibilité descendante. Si vous devez définir des dates particulières ou effectuer une arithmétique des dates, utilisez un calendrier. Les calendriers gèrent également la localisation. Les fonctions de manipulation de date précédentes de Date ont depuis été dépréciées.

Personnellement, j'ai tendance à utiliser le temps en millisecondes comme long (ou long, selon le cas) ou le calendrier lorsqu'il y a un choix.

La date et le calendrier sont mutables, ce qui tend à présenter des problèmes lors de l'utilisation de l'une ou l'autre dans une API.


5
Pour info, les anciennes classes de date-heure terriblement gênantes telles que java.util.Date, java.util.Calendaret java.text.SimpleDateFormatsont désormais héritées , supplantées par les classes java.time intégrées à Java 8 et versions ultérieures. Voir Tutoriel par Oracle .
Basil Bourque

67

Le meilleur moyen pour le nouveau code (si votre politique autorise le code tiers) est d'utiliser le bibliothèque Joda Time .

La date et le calendrier ont tous deux tellement de problèmes de conception que ni l'un ni l'autre ne sont de bonnes solutions pour le nouveau code.


7
J'appuie la suggestion d'utiliser le temps joda. Il est plus facile à utiliser et à comprendre et offre beaucoup plus de fonctionnalités que vous pouvez utiliser.
Jeroen van Bergen

30
Pour une discussion sur l'opportunité d'utiliser Joda Time ou de s'en tenir aux classes JDK standard, voir stackoverflow.com/questions/589870/…
Jonik

3
Je ne sais pas si cela mérite des votes négatifs, mais cela ne répond pas à la question. Pourrait être mieux en tant que commentaire.
IcedDante

7
Parce que la question portait sur l'utilisation de la date et du calendrier sans utiliser une bibliothèque tierce qui ajoute un risque de dépendance d'un fournisseur unique à un projet.
Archimède Trajano

3
C'était le "meilleur moyen" jusqu'à ce que le package java.time soit disponible avec Java 8.
DaBlick

58
  • Dateet Calendarsont vraiment le même concept fondamental (les deux représentent un instant dans le temps et sont des enveloppes autour d'une longvaleur sous-jacente ).

  • On pourrait dire qu'il Calendarest en fait encore plus cassé qu'il ne l'Date est, car il semble offrir des faits concrets sur des choses comme le jour de la semaine et l'heure du jour, alors que si vous changez sa timeZonepropriété, le béton se transforme en blancmange! Aucun des deux objets n'est vraiment utile comme magasin d' année-mois-jour ou d' heure pour cette raison.

  • Utilisez Calendaruniquement comme une calculatrice qui, une fois donnée Dateet des TimeZoneobjets, fera des calculs pour vous. Évitez son utilisation pour la saisie de propriété dans une application.

  • À utiliser SimpleDateFormatavec TimeZoneet Datepour générer des chaînes d'affichage.

  • Si vous vous sentez aventureux, utilisez Joda-Time, bien qu'il soit inutilement compliqué à mon humble avis et qu'il sera bientôt remplacé par l'API de date JSR-310 de toute façon.

  • J'ai déjà répondu qu'il n'est pas difficile de rouler votre propre YearMonthDayclasse, qui utilise Calendarsous le capot pour les calculs de date. J'ai été rétrogradé pour la suggestion, mais je pense toujours qu'elle est valable car Joda-Time (et JSR-310 ) sont vraiment trop compliqués pour la plupart des cas d'utilisation.


1
Y a-t-il un délai pour le JSR310? Cela allait être dans Java 7, mais je pense que ce n'est plus le cas actuellement.
Brian Agnew

@Brian - c'est certainement devenu très silencieux sur cette liste de diffusion!
oxbow_lakes

Je vérifie, c'est devenu inactif, ce qui signifie qu'ils n'ont pas publié de projet d'étape depuis 18 mois :-(
Brian Agnew

Le commentaire le plus récent sur la liste de diffusion date de juillet et de Stephen, donc le projet est probablement encore en marche
oxbow_lakes

D'accord. Si vous savez comment utiliser la date en toute sécurité en tant qu'objet immuable et le calendrier pour manipuler les dates, la plupart des gens devraient être en sécurité. Soyez prudent lorsque vous utilisez SimpleDateFormat dans du code multithread.
cwash

25

La date est idéale pour stocker un objet de date. C'est celui qui persiste, celui qui est sérialisé ...

Le calendrier est idéal pour manipuler les dates.

Remarque: nous privilégions parfois java.lang.Long par rapport à Date, car Date est modifiable et donc pas thread-safe. Sur un objet Date, utilisez setTime () et getTime () pour basculer entre les deux. Par exemple, une Date constante dans l'application (exemples: le zéro 1970/01/01, ou un END_OF_TIME applicatif que vous définissez sur 2099/12/31; ceux-ci sont très utiles pour remplacer les valeurs nulles comme heure de début et heure de fin, en particulier lorsque vous les persistez dans la base de données, car SQL est si particulier avec des valeurs nulles).


Je java.lang.Long
suppose que

17

J'utilise généralement Date si possible. Bien qu'il soit mutable, les mutateurs sont en fait obsolètes. En fin de compte, il enveloppe essentiellement un long qui représenterait la date / heure. Inversement, j'utiliserais des calendriers si je dois manipuler les valeurs.

Vous pouvez y penser de cette façon: vous n'utilisez StringBuffer que lorsque vous avez besoin d'avoir des chaînes que vous pouvez facilement manipuler puis les convertir en chaînes en utilisant la méthode toString (). De la même manière, je n'utilise Calendar que si j'ai besoin de manipuler des données temporelles.

Pour les meilleures pratiques, j'ai tendance à utiliser autant que possible des objets immuables en dehors du modèle de domaine . Cela réduit considérablement les risques d'effets secondaires et cela est fait pour vous par le compilateur, plutôt que par un test JUnit. Vous utilisez cette technique en créant des champs finaux privés dans votre classe.

Et revenons à l'analogie StringBuffer. Voici un code qui vous montre comment convertir entre le calendrier et la date

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);

Oui, les objets immuables ont un sens pour le travail date-heure. Les classes java.time qui ont supplanté Date/ Calendarutilisé le modèle d'objets immuables.
Basil Bourque

C'est peut-être vrai, mais pas en 2010.
Archimedes Trajano

Oui. Mais il y a des milliers de personnes qui lisent cette page maintenant , plus de 150 000 à ce jour. Mon commentaire est une note pour eux, pas une critique de vous.
Basil Bourque

Je sais, c'est pourquoi j'ai voté contre l'autre réponse. Cependant, il y a encore des gens qui ont besoin de souffrir avec les anciens JDK qui ont également besoin de la réponse ci-dessus.
Archimedes Trajano

1
En fait, pour Java 6 et 7, nous avons le projet ThreeTen-Backport . Cela apporte la plupart des fonctionnalités de java.time avec pratiquement la même API. Il n'est donc pas nécessaire d'utiliser ces terribles classes de date et d'heure héritées.
Basil Bourque

15

Dates doivent être utilisés comme des points immuables dans le temps; CalendarLes s sont modifiables et peuvent être transmis et modifiés si vous avez besoin de collaborer avec d'autres classes pour trouver une date finale. Considérez-les comme analogues StringetStringBuilder et vous comprendrez comment je considère qu'ils devraient être utilisés.

(Et oui, je sais que la date n'est pas réellement immuable techniquement, mais l'intention est qu'elle ne devrait pas être modifiable, et si rien n'appelle les méthodes obsolètes, alors c'est le cas.)


Oui, les objets immuables ont un sens pour le travail date-heure. Les classes java.time qui ont supplanté Date/ Calendarutilisé le modèle d'objets immuables. Spécifiquement, Instantremplace java.util.Dateet ZonedDateTimeremplace Calendar/ GregorianCalendar.
Basil Bourque

15

tl; dr

conseiller les "meilleures pratiques" actuelles autour DateetCalendar

est - il préférable de favoriser toujours CalendarplusDate

Évitez complètement ces classes héritées . Utilisez plutôt des classes java.time .

Tableau de tous les types de date-heure en Java, à la fois modernes et hérités

Détails

La réponse par Ortomala Lokni a raison de suggérer d' utiliser les modernes java.time les classes plutôt que les classes date du temps de l' héritage vieux gênants ( Date, Calendar, etc.). Mais cette réponse suggère la mauvaise classe comme équivalente (voir mon commentaire sur cette réponse).

Utilisation de java.time

Les classes de java.time sont une grande amélioration par rapport à la classe date temps anciens, la différence nuit et jour. Les anciennes classes sont mal conçues, déroutantes et gênantes. Vous devriez éviter les anciennes classes autant que possible. Mais lorsque vous avez besoin de convertir vers / à partir de l'ancien / nouveau, vous pouvez le faire en appelant de nouvelles méthodes à ajouter aux anciennes classes.

Pour plus d'informations sur la conversion, voir ma réponse et le diagramme astucieux vers une autre question, Convertir java.util.Date en quel type «java.time»? .

La recherche de débordement de pile donne plusieurs centaines d'exemples de questions et réponses sur l'utilisation de java.time. Mais voici un bref résumé.

Instant

Obtenez le moment actuel avec un Instant. La Instantclasse représente un moment sur la chronologie en UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).

Instant instant = Instant.now();

ZonedDateTime

Pour voir ce même moment simultané à travers l'objectif de l' heure d'une horloge murale d'une région particulière , appliquez un fuseau horaire ( ZoneId) pour obtenir un ZonedDateTime.

Fuseau horaire

Indiquez un nom de fuseau horaire approprié dans le format continent/region, tels que America/Montreal, Africa/Casablancaou Pacific/Auckland. N'utilisez jamais l'abréviation de 3 à 4 lettres telles que ESTou ISTcar ce ne sont pas de véritables fuseaux horaires, ni standardisés, ni même uniques (!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();

Décalage

Un fuseau horaire est l'histoire d'une région dans laquelle son décalage par rapport à l'UTC a changé . Mais parfois, vous ne recevez qu'un décalage sans la zone complète. Dans ce cas, utilisez la OffsetDateTimeclasse.

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

L'utilisation d'un fuseau horaire est préférable à l'utilisation d'un simple décalage.

LocalDateTime

Le «Local» dans les Local…classes signifie n'importe quelle localité, pas une localité particulière. Le nom peut donc être contre-intuitif.

LocalDateTime, LocalDateEt LocalTimedélibérément manque aucune information sur la zone de décalage ou de temps. Ils ne représentent donc pas des moments réels, ce ne sont pas des points sur la chronologie. En cas de doute ou de confusion, utilisez ZonedDateTimeplutôt que LocalDateTime. Search Stack Overflow pour plus de discussion.

Cordes

Ne confondez pas les objets date-heure avec des chaînes qui représentent leur valeur. Vous pouvez analyser une chaîne pour obtenir un objet date-heure et vous pouvez générer une chaîne à partir d'un objet date-heure. Mais la chaîne n'est jamais la date-heure elle-même.

Découvrez les formats ISO 8601 standard, utilisés par défaut dans les classes java.time.


À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, &SimpleDateFormat .

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers java.time classes .

Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Utilisant un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure, vous pouvez échanger des objets java.time directement avec votre base de données. Pas besoin de chaînes ni de classes java.sql. *.

Où obtenir les classes java.time?

  • Java SE 8 , Java SE 9 et versions ultérieures
    • Intégré.
    • Une partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et correctifs mineurs.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android

Tableau de la bibliothèque java.time à utiliser avec quelle version de Java ou Android

Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour de futurs ajouts possibles à java.time. Vous trouverez peut - être des classes utiles ici, comme Interval, YearWeek, YearQuarteret plus .


10

Avec Java 8, le nouveau package java.time doit être utilisé.

Les objets sont immuables, les fuseaux horaires et l'heure d'été sont pris en compte.

Vous pouvez créer un ZonedDateTimeobjet à partir d'un ancien java.util.Dateobjet comme ceci:

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());

Bon de suggérer les classes java.time. Mais mauvais à suggérer LocalDateTime. Cette classe perd volontairement toute information sur le décalage par rapport à l'UTC et le fuseau horaire. Cette classe n'est donc pas équivalente comme Dateen UTC et Calendara un fuseau horaire attribué. Voir ma réponse et le diagramme astucieux à une autre question, convertir java.util.Date en quel type "java.time"? .
Basil Bourque

9

Je préconise toujours Joda-time . Voici pourquoi.

  1. l'API est cohérente et intuitive. Contrairement aux API java.util.Date/Calendar
  2. il ne souffre pas de problèmes de thread, contrairement à java.text.SimpleDateFormat, etc.
  3. c'est la base des nouvelles API date / heure Java ( JSR310 , prévues pour Java 8. Vous utiliserez donc des API qui deviendront des API Java de base.

EDIT: Les classes de date / heure Java introduites avec Java 8 sont maintenant la solution préférée, si vous pouvez migrer vers Java 8


3
La dernière fois que j'ai regardé, JODA et JSR-310 étaient très différents, même s'ils sont tous les deux écrits par Stephen Colebourne. Cela dit, JODA vous présenterait la complexité des problèmes de date et d'heure que JSR-310 résout également
oxbow_lakes

2
Parce que la question portait sur l'utilisation de la date et du calendrier sans utiliser une bibliothèque tierce qui ajoute un risque de dépendance d'un fournisseur unique à un projet.
Archimède Trajano

2
Je maintiens que la meilleure pratique est simplement de ne pas utiliser ces cours
Brian Agnew

3
Étant donné les problèmes connus avec les classes java.util.Date et Calendar, suggérer Joda-Time (ou JSR 310) me semble approprié et responsable. Nous ne parlons pas d'une question de goût ou de style esthétique. Si quelqu'un a demandé s'il fallait prendre la voiture rouge ou la voiture argentée et que je savais que la voiture rouge avait un pneu crevé et la voiture argentée avait un radiateur éclaté, devrais-je choisir une voiture ou devrais-je suggérer d'appeler un taxi? La réponse à cette question devrait sembler évidente de nos jours car même Sun / Oracle a décidé de laisser ces junkers et d'acheter une nouvelle voiture: JSR 310: Date and Time API.
Basil Bourque

1
Pour info, le projet Joda-Time est désormais en mode maintenance , conseillant la migration vers les classes java.time . Voir Tutoriel par Oracle .
Basil Bourque

8

Un peu en retard à la fête, mais Java a une nouvelle API Date Time dans JDK 8. Vous pouvez mettre à niveau votre version JDK et adopter la norme. Plus de date / calendrier en désordre, plus de pots tiers.


1

La date devrait être re-développée. Au lieu d'être un entier long, il devrait contenir l'année, le mois, la date, l'heure, la minute, la seconde, comme des champs séparés. Il peut même être utile de stocker le calendrier et le fuseau horaire auxquels cette date est associée.

Dans notre conversation naturelle, si vous fixez un rendez-vous le 1er novembre 2013 à 13 h, heure de New York, il s'agit d'un DateTime. Ce n'est PAS un calendrier. Nous devrions donc pouvoir converser comme ça en Java également.

Lorsque la date est stockée sous la forme d'un entier long (en mili secondes depuis le 1er janvier 1970 ou quelque chose comme ça), le calcul de sa date actuelle dépend du calendrier. Différents calendriers donneront une date différente. C'est dans la perspective de donner un temps absolu (par exemple 1 billion de secondes après le Big Bang). Mais souvent, nous avons également besoin d'un moyen de conversation pratique, comme un objet encapsulant l'année, le mois, etc.

Je me demande s'il y a de nouvelles avancées en Java pour concilier ces 2 objectifs. Peut-être que mes connaissances en java sont trop anciennes.


Le fait que vous puissiez stocker le même instant dans le temps, mais signaler des heures / minutes / jours / semaines / années / foo différents en fonction de différents systèmes de calendrier, est une force, pas une faiblesse. Il reflète la réalité (complexe).
ThrawnCA

En effet, Datea été re-développé; remplacé par la java.time.Instantclasse. Et Calendar/ a GregorianCalendarété remplacé par la java.time.ZonedDateTimeclasse.
Basil Bourque

0

Btw "date" est généralement étiqueté comme "obsolète / obsolète" (je ne sais pas exactement pourquoi) - quelque chose à ce sujet est écrit ici Java: Pourquoi le constructeur Date est-il obsolète, et que dois-je utiliser à la place?

Il semble que ce soit un problème du constructeur uniquement via la nouvelle date (année int, mois int, jour int) , la manière recommandée est via Calendrier et définir les paramètres séparément .. ( Calendrier cal = Calendar.getInstance (); )


0

J'utilise Calendrier lorsque j'ai besoin d'opérations spécifiques sur les dates comme le déplacement dans le temps, mais Date, je trouve cela utile lorsque vous devez formater la date pour adapter vos besoins, récemment j'ai découvert que Locale a beaucoup d'opérations et de méthodes utiles. J'utilise Locale en ce moment!


Pour votre information, la problématique Calendaret les Dateclasses ont été supplanté il y a quelques années par les java.time classes. Pas besoin de jamais utiliser Dateou Calendar. Et Localen'a rien à voir avec la signification des objets date-heure. A Localeest uniquement utilisé pour spécifier le langage humain et les normes culturelles à utiliser pour la localisation tout en générant du texte pour représenter la valeur d'un objet date-heure.
Basil Bourque
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.