Date de Java vs calendrier

est-ce que quelqu'un pourrait conseiller la" meilleure pratique "actuelle autour des types Date et Calendar ?

lors de l'écriture d'un nouveau code, est-il préférable de toujours préférer Calendar à Date , ou y a-t-il des circonstances où Date est le type de données le plus approprié?

341
demandé sur Seraphim's 2009-09-10 13:09:59

13 réponses

Date est une classe plus simple et est principalement là pour des raisons de rétrocompatibilité. Si vous avez besoin de fixer des dates particulières ou de faire de l'arithmétique des dates, utilisez un calendrier. Les calendriers gèrent également la localisation. Les fonctions précédentes de manipulation de Date ont depuis été dépréciées.

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

la Date et le calendrier sont modifiables, ce qui a tendance à présenter des problèmes lors de l'utilisation dans une API.

360
répondu cletus 2009-09-10 09:11:53

la meilleure façon d'utiliser le nouveau code (si votre police autorise le code de tiers) est d'utiliser la bibliothèque Joda Time .

les deux, Date et calendrier , ont tellement de problèmes de conception que ni l'une ni l'autre ne sont de bonnes solutions pour le nouveau code.

67
répondu dmeister 2013-05-26 12:05:19
  • Date et Calendar sont vraiment le même concept fondamental (tous deux représentent un instant in time et sont enveloppants autour d'une valeur sous-jacente long ).

  • on pourrait soutenir que Calendar est en fait encore plus cassé que Date est, car il semble offrir des faits concrets sur des choses comme le jour de la semaine et l'Heure de la journée, alors que si vous changez sa propriété timeZone , le béton se transforme en blanc-manger! Ni l'un ni l'autre des objets ne sont vraiment utiles comme un magasin de Année-Mois-Jour ou Heure-de-jour pour cette raison.

  • utilisez Calendar seulement comme calculatrice qui, lorsqu'elle est donnée Date et TimeZone objets, fera des calculs pour vous. Évitez son utilisation pour la saisie de propriété dans une application.

  • utilisez SimpleDateFormat avec TimeZone et Date pour générer des chaînes d'affichage.

  • si vous vous sentez aventureux utilisez Joda-Time, bien qu'il soit inutilement compliqué IMHO et sera bientôt remplacé par le JSR-310 date API dans tous les cas.

  • j'ai répondu avant qu'il n'est pas difficile de rouler votre propre classe YearMonthDay , qui utilise Calendar sous la hotte pour le calcul de la date. J'ai été rétrogradé pour la suggestion mais je crois toujours qu'elle est valide parce que Joda-Time (et JSR-310 ) sont vraiment trop compliquées pour la plupart des cas d'utilisation.

53
répondu oxbow_lakes 2014-01-08 20:57:41

Date est le meilleur pour stocker un objet date. C'est le persisté, la Sérialisé ...

Le calendrier

est le meilleur pour manipuler les Dates.

Note: Nous préférons aussi parfois java.lang.Long over Date, parce que Date est mutable et donc pas sûr de fil. 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 une application END_OF_TIME que vous définissez à 2099/12/31 ; ceux-ci sont très utiles pour remplacer les valeurs nulles comme l'Heure de début et l'Heure de fin, surtout quand vous les persistez dans la base de données, car SQL est si particulier avec nulls).

25
répondu KLE 2009-09-10 09:22:26

j'utilise généralement la Date si possible. Bien qu'il soit mutable, les mutants sont en fait dépréciés. En fin de compte, il enroule essentiellement un long qui représenterait la date/heure. À l'inverse, j'utiliserais des calendriers si je devais manipuler les valeurs.

vous pouvez penser à cela de cette façon: vous n'utilisez StringBuffer que lorsque vous avez besoin d'avoir des chaînes que vous pouvez facilement manipuler et ensuite les convertir en Chaînes en utilisant la méthode toString (). De la même manière, je ne l'utilise Calendrier si je dois manipuler des données temporelles.

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

et revenons à L'analogie de 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);
17
répondu Archimedes Trajano 2011-04-12 14:55:35

Date s doivent être utilisés comme points immuables dans le temps; Calendar s sont mutables, et peuvent être transmis et modifiés si vous avez besoin de collaborer avec d'autres classes pour venir avec une date finale. Considérez - les comme String et StringBuilder et vous comprendrez comment je considère qu'ils devraient être utilisés.

(et oui, je sais que la Date n'est pas techniquement immuable, mais l'intention est qu'elle ne soit pas mutable, et si rien n'appelle la méthodes dépréciées alors il en est ainsi.)

15
répondu Andrzej Doyle 2009-09-10 09:38:30

avec Java 8, le nouveau java.le paquet temporel doit être utilisé.

Les objets

sont immuables, les fuseaux horaires et l'économie de lumière de jour sont pris en compte.

vous pouvez créer un ZonedDateTime objet d'un ancien java.util.Date objet comme ceci:

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
10
répondu Ortomala Lokni 2017-02-28 08:35:34

j'ai toujours l'avocat Joda-time . Voici pourquoi.

  1. L'API est cohérente et intuitive. Contrairement à la java.util.Date / Calendrier APIs
  2. il ne souffre pas de problèmes de threading, contrairement à java.texte.SimpleDateFormat etc. (J'ai vu de nombreux problèmes de client liés à ne pas se rendre compte que la date/heure standard formatage n'est pas thread-safe)
  3. c'est la base de la nouvelle API Date/heure Java ( JSR310 , prévue pour Java 8. Vous utiliserez donc des API qui deviendront des API Java core.
9
répondu Brian Agnew 2014-01-09 09:55:05

tl; dr

conseiller le courant de la "meilleure pratique" autour de Date et Calendar

est-il préférable de toujours favoriser Calendar plutôt que Date

évitez ces classes héritées entièrement. Utilisez java.heure classes à la place.

  • Pour un moment UTC , l'utilisation Instant

    (l'équivalent moderne de Date )
  • pour un moment dans un particulier fuseau horaire , utiliser ZonedDateTime

    (l'équivalent moderne de GregorianCalendar )
  • pour un moment dans un particulier offset-from-UTC , utiliser OffsetDateTime

    (pas d'équivalent dans les classes legacy)
  • Pour une date en temps (pas un instant) avec de temps inconnu de la zone ou de décalage, l'utilisation LocalDateTime

    (pas d'équivalent dans les classes héritées)

détails

Le Réponse en Ortomala Lokni est en droit de proposer à l'aide de la moderne de java.temps classes plutôt que le vieil héritage gênant classes de date-heure ( Date , Calendar , etc.). Mais cette Réponse suggère la mauvaise classe comme équivalent (voir mon commentaire sur cette Réponse).

utilisant java.time

La java.les classes de temps sont une vaste amélioration par rapport à l'héritage date-heure classes, nuit et jour différence. Les anciennes classes sont mal conçues, déroutantes et gênantes. Dans la mesure du possible, évitez les anciennes classes. Mais quand vous avez besoin de convertir vers/à partir de l'ancienne / nouvelle, vous pouvez le faire en appelant les nouvelles méthodes Ajouter aux classes ancienne .

pour beaucoup plus d'informations sur la conversion, voir ma réponse et le diagramme nifty à une autre Question, convertir java.util.La Date de ce "java.temps" type? .

Searching Stack Overflow donne des centaines d'exemples de Questions et de réponses sur l'utilisation de java.temps. Mais voici un rapide résumé.

Instant

Obtenir à l'heure actuelle, avec un Instant . La classe Instant représente un moment sur la ligne de temps dans UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).

Instant instant = Instant.now();

ZonedDateTime

pour voir que même moment simultané à travers la lentille d'une région particulière wall-clock time , appliquer un fuseau horaire( ZoneId ) pour obtenir un ZonedDateTime .

fuseau horaire

spécifier un nom du fuseau horaire approprié dans le format de continent/region , tel que America/Montreal , Africa/Casablanca , ou Pacific/Auckland . N'utilisez jamais l'abréviation de 3-4 lettres comme EST ou IST car ils sont pas vrai fuseaux horaires, non standardisé, et même pas unique(!).

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

Offset

un fuseau horaire est l'histoire d'une région de changements dans son offset-from-UTC . Mais parfois on ne vous donne qu'un décalage sans la pleine zone. Dans ce cas, utilisez la classe OffsetDateTime .

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

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

LocalDateTime

le "Local" dans les classes Local… signifie toute "localité 1519990920", et non une localité particulière. Si le nom peut être contre-intuitif.

LocalDateTime , LocalDate , et LocalTime manquent délibérément toute information sur offset ou fuseau horaire. Donc ils font pas représentent des moments réels, ils sont et non points sur la ligne de temps. En cas de doute ou de confusion, utilisez ZonedDateTime plutôt que LocalDateTime . Rechercher le débordement de la pile pour plus de discussion.

cordes

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

en savoir plus sur les formats standard ISO 8601 , utilisés par défaut en java.les classes de temps.


à Propos de de java.heure

Le de java.time framework est construit dans Java 8 et plus tard. Ces classes remplacent l'ancienne legacy date-heure des classes telles que java.util.Date , Calendar , & SimpleDateFormat .

le Joda-Time projet, maintenant en mode maintenance , conseille la migration vers le java.temps classes.

pour en savoir plus, voir le Oracle Tutorial . Et rechercher le débordement de la pile pour de nombreux exemples et explications. La spécification est JSR 310 .

utilisant un pilote JDBC conforme à JDBC 4.2 ou plus tard, vous pouvez échanger java.temps objets directement avec votre base de données. Pas besoin de chaînes ni de java.SQL.* classe.

où obtenir le java.les classes de temps?

ThreeTen-Extra " le projet étend java.temps avec des classes supplémentaires. Ce projet est un terrain d'expérimentation pour d'éventuelles futures additions à java.temps. Vous pouvez trouver ici quelques cours utiles tels que: Interval , YearWeek , YearQuarter , et plus .

9
répondu Basil Bourque 2018-02-23 00:23:23

un peu en retard à la fête, mais Java a une nouvelle API Date Time dans JDK 8. Vous pouvez mettre à jour votre version JDK et adopter la norme. Plus de date/calendrier confus, plus de pots de tierce partie.

8
répondu Silviu Burcea 2014-05-23 07:26:19
La Date

devrait être revue. Au lieu d'être un long interger, il devrait tenir Année, Mois, date, Heure, minute, Seconde, comme des champs séparés. Il pourrait même être bon de stocker le calendrier et le fuseau horaire auxquels cette date est associée.

dans notre conversation naturelle, si la configuration d'un rendez-vous à Nov. 1, 2013 1pm de new-york, c'est un DateTime. Ce n'est pas un calendrier. Nous devrions donc être capables de converser comme cela en Java aussi.

lorsque la Date est stockée comme un long entier (de mili secondes depuis le 1er janvier 1970 ou quelque chose), le calcul de sa date actuelle dépend du calendrier. Différents calendriers indiqueront des dates différentes. C'est de la perspective de donner un temps absolu (par exemple 1 trillion de secondes après le Big Bang). Mais souvent, nous avons également besoin d'un moyen pratique de conversation, comme un objet encapsulant année, mois, etc

je me demande s'il y a de nouvelles avancées en Java pour concilier ces deux objectifs. Peut-être que ma connaissance de java est trop vieux.

1
répondu user2835562 2013-10-01 15:46:03

Btw "date" est généralement étiqueté comme "obsolète / obsolète" (je ne sais pas exactement pourquoi) - quelque chose est écrit là Java: pourquoi le constructeur de Date est-il déprécié, et qu'est-ce que j'utilise à la place?

il semble que c'est un problème du constructeur seulement - voie via nouvelle Date(int année, int mois, int jour) , voie recommandée est via calendrier et params séparément .. ( Calendrier cal = Calendrier.getInstance (); )

0
répondu xxxvodnikxxx 2017-05-23 12:18:25

J'utilise le calendrier quand j'ai besoin d'opérations spécifiques au cours des dates comme le déplacement dans le temps, mais la Date je trouve utile quand vous avez besoin de 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.Donc j'utilise Locale en ce moment!

0
répondu Brian Nelson 2018-07-02 21:29:35