253 votes

Java : Pourquoi le constructeur Date est-il déprécié, et que dois-je utiliser à la place ?

Je viens du monde C#, donc je n'ai pas encore beaucoup d'expérience avec Java. Eclipse vient de me dire que Date a été déprécié :

Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));

Pourquoi ? Et qu'est-ce qui devrait être utilisé à la place (surtout dans les cas comme ci-dessus) ?

45 votes

Je suis en train de vivre une courbe d'apprentissage similaire, passant également de C# à Java. L'autre chose qui m'a piqué est que le mois de l'année est un système basé sur 0 (0 à 11 où Jan. = 0 et Dec. = 11) mais les jours du mois sont basés sur 1 (1 à 31). Attention à ce problème !

3 votes

@Paul Sasik, oui, mais il existe une constante Calendar.JANUARY par exemple, et une pour chaque mois.

1 votes

273voto

BuffaloBuffalo Points 4020

Le site java.util.Date n'est pas réellement dépréciée, c'est juste ce constructeur, ainsi que quelques autres constructeurs/méthodes qui sont dépréciés. Il a été déprécié parce que ce type d'utilisation ne fonctionne pas bien avec l'internationalisation. Le site Calendar doit être utilisée à la place :

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();

Jetez un coup d'œil à la Javadoc de la date :

http://download.oracle.com/javase/6/docs/api/java/util/Date.html

2 votes

Cela devrait être la meilleure réponse. Merci.

0 votes

En disant "ne fonctionne pas bien avec l'internationalisation", voulez-vous dire que pour une date, vous ne pouvez pas lui attribuer de TimeZone ? Merci

0 votes

Ce que Date a fait, c'est analyser une chaîne de caractères, donc à la place nous devons maintenant soustraire une chaîne de caractères qui contient l'année, le mois et le jour ? Cela semble être beaucoup de tracas supplémentaires pour quelque chose qui, dans la plupart des cas, n'a pas besoin d'une logique et de méthodes aussi complexes.

108voto

Basil Bourque Points 8938

Tl;dr

LocalDate.of( 1985 , 1 , 1 )

ou

LocalDate.of( 1985 , Month.JANUARY , 1 )

Détails

Le site java.util.Date , java.util.Calendar y java.text.SimpleDateFormat Les classes ont été précipitées trop rapidement lorsque Java a été lancé et a évolué. Les classes n'étaient pas bien conçues ou implémentées. Des améliorations ont été tentées, d'où les dépréciations que vous avez trouvées. Malheureusement, ces tentatives d'amélioration ont largement échoué. Vous devriez éviter ces classes tout à fait. Elles sont supprimées dans Java 8 par de nouvelles classes.

Problèmes dans votre code

Une date java.util.Date possède à la fois une partie date et une partie heure. Vous avez ignoré la partie heure dans votre code. La classe Date prendra donc le début de la journée tel que défini par le fuseau horaire par défaut de votre JVM et appliquera cette heure à l'objet Date. Les résultats de votre code varieront donc en fonction de la machine sur laquelle il est exécuté ou du fuseau horaire défini. Ce n'est probablement pas ce que vous souhaitez.

Si vous ne voulez que la date, sans la partie temps, comme pour une date de naissance, vous ne voudrez peut-être pas utiliser une balise Date objet. Vous pouvez vouloir stocker juste une chaîne de caractères de la date, dans l'objet ISO 8601 format de YYYY-MM-DD . Ou utilisez un LocalDate de Joda-Time (voir ci-dessous).

Joda-Time

Première chose à apprendre en Java : Évitez les classes java.util.Date et java.util.Calendar, réputées pour leurs difficultés. fourni avec Java.

Comme il a été correctement noté dans la réponse de user3277382 utilisez soit Joda-Time ou le nouveau paquet java.time.* en Java 8.

Exemple de code en Joda-Time 2.3

DateTimeZone timeZoneNorway = DateTimeZone.forID( "Europe/Oslo" );
DateTime birthDateTime_InNorway = new DateTime( 1985, 1, 1, 3, 2, 1, timeZoneNorway );

DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime birthDateTime_InNewYork = birthDateTime_InNorway.toDateTime( timeZoneNewYork ); 

DateTime birthDateTime_UtcGmt = birthDateTime_InNorway.toDateTime( DateTimeZone.UTC );

LocalDate birthDate = new LocalDate( 1985, 1, 1 );

Dump à la console

System.out.println( "birthDateTime_InNorway: " + birthDateTime_InNorway );
System.out.println( "birthDateTime_InNewYork: " + birthDateTime_InNewYork );
System.out.println( "birthDateTime_UtcGmt: " + birthDateTime_UtcGmt );
System.out.println( "birthDate: " + birthDate );

Quand on court

birthDateTime_InNorway: 1985-01-01T03:02:01.000+01:00
birthDateTime_InNewYork: 1984-12-31T21:02:01.000-05:00
birthDateTime_UtcGmt: 1985-01-01T02:02:01.000Z
birthDate: 1985-01-01

java.time

Dans ce cas, le code pour java.time est presque identique à celui de Joda-Time .

Nous obtenons un fuseau horaire ( ZoneId ), et construire un objet date-heure affecté à ce fuseau horaire ( ZonedDateTime ). Ensuite, en utilisant le Objets immuables nous créons de nouvelles dates-horaires basées sur l'instant même de l'ancien objet (nombre de nanosecondes écoulées depuis le début de l'année). époque ) mais a attribué un autre fuseau horaire. Enfin, nous obtenons un LocalDate qui n'a ni heure du jour ni fuseau horaire, mais remarquez que le fuseau horaire s'applique lors de la détermination de cette date (un nouveau jour se lève plus tôt dans l'UE). Oslo que dans New York par exemple).

ZoneId zoneId_Norway = ZoneId.of( "Europe/Oslo" );
ZonedDateTime zdt_Norway = ZonedDateTime.of( 1985 , 1 , 1 , 3 , 2 , 1 , 0 , zoneId_Norway );

ZoneId zoneId_NewYork = ZonedId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt_Norway.withZoneSameInstant( zoneId_NewYork );

ZonedDateTime zdt_Utc = zdt_Norway.withZoneSameInstant( ZoneOffset.UTC );  // Or, next line is similar.
Instant instant = zdt_Norway.toInstant();  // Instant is always in UTC.

LocalDate localDate_Norway = zdt_Norway.toLocalDate();

À propos de java.time

Le site java.time est intégré à Java 8 et aux versions ultérieures. Ces classes remplacent les anciennes classes héritage les classes de date et d'heure telles que java.util.Date , Calendar , & SimpleDateFormat .

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

Le site Joda-Time Le projet, actuellement en mode de maintenance conseille la migration vers le java.time classes.

Vous pouvez échanger java.time directement avec votre base de données. Utilisez un Pilote JDBC conforme à JDBC 4.2 ou plus tard. Pas besoin de ficelles, pas besoin de java.sql.* classes. Support de Hibernate 5 et JPA 2.2 java.time .

Où obtenir les classes java.time ?

Table of which java.time library to use with which version of Java or Android

5 votes

Félicitations pour avoir mentionné la cause première et avoir présenté toutes les alternatives disponibles.

1 votes

C'est la bonne réponse et la classe Calendrier est à éviter. ThreeTen est la meilleure option

0 votes

@Basil Bourque Vous mentionnez des versions ultérieures de l'implémentation des classes java.time dans les paquets Android. Pouvez-vous être plus précis quant aux versions ? J'essaie de remplacer l'ancien code Date et Calendrier d'une application Android et je ne sais pas par où commencer.

104voto

Ruben Points 4459

La spécificité Date est déprécié, et Calendar doit être utilisé à la place. Le site JavaDoc para Date décrit les constructeurs qui sont dépréciés et la façon de les remplacer en utilisant un fichier de type Calendar .

31 votes

Calendar nécessite un objet supplémentaire et 8 lignes de code de plus pour faire la même chose, c'est-à-dire créer un objet Date d'après ce que je sais. C'est confus et semble inutile quand on a juste besoin d'une date et non d'une variable ajustée au fuseau horaire.

7 votes

Pour information, les anciennes classes de date et d'heure terriblement gênantes telles que java.util.Date , java.util.Calendar y java.text.SimpleDateFormat sont maintenant héritage supprimé par le java.time intégrées à Java 8 et aux versions ultérieures. Voir Tutoriel par Oracle .

12voto

Stephen C Points 255558

L'une des raisons pour lesquelles le constructeur est déprécié est que la signification du paramètre année n'est pas celle à laquelle on pourrait s'attendre. La javadoc dit :

A partir de la version 1.1 du JDK, remplacé par Calendar.set(year + 1900, month, date) .

Notez que le champ année correspond au nombre d'années écoulées depuis que l'entreprise a été créée. 1900 Il est donc fort probable que votre exemple de code ne fasse pas ce que vous attendez de lui. Et c'est bien là le problème.

En général, le Date L'API ne prend en charge que le calendrier occidental moderne, a des composants spécifiés de manière idiosyncratique et se comporte de manière incohérente si vous définissez des champs.

Le site Calendar y GregorianCalendar sont meilleures que les Date et les API tierces de Joda-time étaient généralement considérées comme les meilleures. Dans Java 8, ils ont introduit la java.time et ceux-ci sont maintenant l'alternative recommandée.

0 votes

Cette solution fonctionne parfaitement, sauf qu'elle n'utilise pas l'heure zéro pour les heures-minutes-secondes-millisecondes comme le faisait new Date(year, month, day). Nous avons donc besoin de quelque chose comme : Calendar cal = Calendar.getInstance() ; cal.clear() ; cal.set(year + 1900, month, date) ; Date dateRepresentation = cal.getTime() ;

8voto

Zobbl Points 345

Juste en plus http://www.xmission.com/~goodhill/dates/datedeprecation.htm

Google fournira d'autres informations sur le "pourquoi".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X