Introduction à l’API Java 8 Date/Heure

Introduction à l'API Java 8 Date / Time

1. Vue d'ensemble

Java 8 a introduit de nouvelles API pourDate etTime afin de remédier aux lacunes des anciensjava.util.Date etjava.util.Calendar.

Dans le cadre de cet article, commençons par les problèmes rencontrés dans les APIDate etCalendar existantes et voyons comment les nouvelles API Java 8Date etTime les résolvent.

Nous examinerons également certaines des classes principales du nouveau projet Java 8 qui font partie du packagejava.time commeLocalDate,LocalTime, LocalDateTime, ZonedDateTime, Period, Duration et leurs API prises en charge.

Lectures complémentaires:

Utilisation des paramètres de date au printemps

Apprenez à travailler avec les paramètres de date dans Spring MVC

Read more

Vérifier si une chaîne est une date valide en Java

Découvrez différentes manières de vérifier si une chaîne est une date valide en Java.

Read more

2. Problèmes avec les APIDate /Time existantes

  • Thread Safety - Les classesDate etCalendar ne sont pas sûres pour les threads, ce qui laisse aux développeurs le soin de faire face au casse-tête des problèmes de concurrence difficiles à déboguer et d'écrire du code supplémentaire pour gérer la sécurité des threads. Au contraire, les nouvelles APIDate etTime introduites dans Java 8 sont immuables et sécurisées pour les threads, éliminant ainsi ce casse-tête de concurrence des développeurs.

  • APIs Design and Ease of Understanding - Les APIDate etCalendar sont mal conçues avec des méthodes inadéquates pour effectuer les opérations quotidiennes. Les nouvelles API deDate/Time sont centrées sur ISO et suivent des modèles de domaine cohérents pour la date, l'heure, la durée et les périodes. Il existe une grande variété de méthodes utilitaires prenant en charge les opérations les plus courantes.

  • ZonedDate and Time - Les développeurs ont dû écrire une logique supplémentaire pour gérer la logique de fuseau horaire avec les anciennes API, alors qu'avec les nouvelles API, la gestion du fuseau horaire peut être effectuée avecLocal etZonedDate /Time API.

3. Utilisation deLocalDate,LocalTime etLocalDateTime

Les classes les plus couramment utilisées sontLocalDate,LocalTime etLocalDateTime. Comme leurs noms l'indiquent, ils représentent la date / heure locale à partir du contexte de l'observateur.

Ces classes sont principalement utilisées lorsqu'il n'est pas nécessaire que le fuseau horaire soit explicitement spécifié dans le contexte. Dans cette section, nous couvrirons les API les plus couramment utilisées.

3.1. Travailler avecLocalDate

LeLocalDate représentea date in ISO format (yyyy-MM-dd) without time.

Il peut être utilisé pour stocker des dates telles que des anniversaires et des jours de paie.

Une instance de date actuelle peut être créée à partir de l'horloge système comme suit:

LocalDate localDate = LocalDate.now();

LesLocalDate représentant un jour, un mois et une année spécifiques peuvent être obtenus en utilisant la méthode «of» ou en utilisant la méthode «parse». Par exemple, les extraits de code ci-dessous représentent lesLocalDate du 20 février 2015:

LocalDate.of(2015, 02, 20);

LocalDate.parse("2015-02-20");

LeLocalDate fournit diverses méthodes utilitaires pour obtenir une variété d'informations. Jetons un coup d'œil à certaines de ces méthodes d'API.

L'extrait de code suivant obtient la date locale actuelle et ajoute un jour:

LocalDate tomorrow = LocalDate.now().plusDays(1);

Cet exemple obtient la date actuelle et soustrait un mois. Notez comment il accepte unenum comme unité de temps:

LocalDate previousMonthSameDay = LocalDate.now().minus(1, ChronoUnit.MONTHS);

Dans les deux exemples de code suivants, nous analysons la date «2016-06-12» et obtenons respectivement le jour de la semaine et le jour du mois. Notez les valeurs de retour, le premier est un objet représentant lesDayOfWeek tandis que le second dans unint représentant la valeur ordinale du mois:

DayOfWeek sunday = LocalDate.parse("2016-06-12").getDayOfWeek();

int twelve = LocalDate.parse("2016-06-12").getDayOfMonth();

Nous pouvons tester si une date se produit dans une année bissextile. Dans cet exemple, nous testons si la date actuelle est une année bissextile:

boolean leapYear = LocalDate.now().isLeapYear();

La relation entre une date et une autre peut être déterminée avant ou après une autre date:

boolean notBefore = LocalDate.parse("2016-06-12")
  .isBefore(LocalDate.parse("2016-06-11"));

boolean isAfter = LocalDate.parse("2016-06-12")
  .isAfter(LocalDate.parse("2016-06-11"));

Les limites de date peuvent être obtenues à partir d'une date donnée. Dans les deux exemples suivants, nous obtenons leLocalDateTime qui représente le début du jour (2016-06-12T00: 00) de la date donnée et leLocalDate qui représente le début du mois (2016- 06-01) respectivement:

LocalDateTime beginningOfDay = LocalDate.parse("2016-06-12").atStartOfDay();
LocalDate firstDayOfMonth = LocalDate.parse("2016-06-12")
  .with(TemporalAdjusters.firstDayOfMonth());

Voyons maintenant comment nous travaillons avec l'heure locale.

3.2. Travailler avecLocalTime

LeLocalTime représentetime without a date.

Similaire àLocalDate, une instance deLocalTime peut être créée à partir de l'horloge système ou en utilisant les méthodes «parse» et «of». Regardez rapidement certaines des API couramment utilisées ci-dessous.

Une instance desLocalTime actuels peut être créée à partir de l'horloge système comme ci-dessous:

LocalTime now = LocalTime.now();

Dans l'exemple de code ci-dessous,, nous créons unLocalTime représentant 06h30 en analysant une représentation sous forme de chaîne:

LocalTime sixThirty = LocalTime.parse("06:30");

La méthode Factory «of» peut être utilisée pour créer unLocalTime. Par exemple, le code ci-dessous crée desLocalTime représentant 06h30 en utilisant la méthode d'usine:

LocalTime sixThirty = LocalTime.of(6, 30);

L'exemple ci-dessous crée unLocalTime en analysant une chaîne et y ajoute une heure en utilisant l'API «plus». Le résultat seraitLocalTime représentant 07h30:

LocalTime sevenThirty = LocalTime.parse("06:30").plus(1, ChronoUnit.HOURS);

Différentes méthodes de lecture sont disponibles et peuvent être utilisées pour obtenir des unités de temps spécifiques telles que l'heure, les minutes et les secondes, comme ci-dessous:

int six = LocalTime.parse("06:30").getHour();

Nous pouvons également vérifier si une heure spécifique se situe avant ou après une autre heure spécifique. L'exemple de code ci-dessous compare deuxLocalTime pour lesquels le résultat serait vrai:

boolean isbefore = LocalTime.parse("06:30").isBefore(LocalTime.parse("07:30"));

L'heure max, min et midi d'une journée peut être obtenue par des constantes dans la classeLocalTime. Ceci est très utile lorsque vous effectuez des requêtes de base de données pour trouver des enregistrements dans un laps de temps donné. Par exemple, le code ci-dessous représente 23: 59: 59.99:

LocalTime maxTime = LocalTime.MAX

Passons maintenant àLocalDateTime.

3.3. Travailler avecLocalDateTime

LeLocalDateTime est utilisé pour représentera combination of date and time.

C’est la classe la plus utilisée lorsque nous avons besoin d’une combinaison de date et d’heure. La classe offre une variété d’API et nous allons examiner quelques-unes des plus courantes.

Une instance deLocalDateTime peut être obtenue à partir de l'horloge système similaire àLocalDate etLocalTime:

LocalDateTime.now();

Les exemples de code ci-dessous expliquent comment créer une instance à l'aide des méthodes d'usine «de» et «parse». Le résultat serait une instanceLocalDateTime représentant le 20 février 2015, 06h30:

LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);
LocalDateTime.parse("2015-02-20T06:30:00");

Il existe des API utilitaires prenant en charge l'addition et la soustraction d'unités de temps spécifiques, telles que les jours, les mois, l'année et les minutes. Les exemples de code ci-dessous illustrent l'utilisation des méthodes «plus» et «moins». Ces API se comportent exactement comme leurs homologues dansLocalDate etLocalTime:

localDateTime.plusDays(1);
localDateTime.minusHours(2);

Des méthodes d'accès rapide sont disponibles pour extraire des unités spécifiques similaires aux classes de date et d'heure. Étant donné l'instance ci-dessus deLocalDateTime, l'exemple de code ci-dessous renverra le mois de février:

localDateTime.getMonth();

4. Utilisation de l'APIZonedDateTime

Java 8 provides ZonedDateTime # [.typ] #quand nous devons gérer la date et l'heure spécifiques au fuseau horaire. LeZoneId est un identifiant utilisé pour représenter différentes zones. Il existe environ 40 fuseaux horaires différents et lesZoneId sont utilisés pour les représenter comme suit.

Dans cet extrait de code, nous créons unZone pour Paris:

ZoneId zoneId = ZoneId.of("Europe/Paris");

Un ensemble de tous les identifiants de zone peut être obtenu comme suit:

Set allZoneIds = ZoneId.getAvailableZoneIds();

LesLocalDateTime peuvent être convertis dans une zone spécifique:

ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);

LeZonedDateTime fournit la méthodeparse pour obtenir l'heure de la date spécifique au fuseau horaire:

ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");

Une autre façon de travailler avec le fuseau horaire consiste à utiliserOffsetDateTime. LeOffsetDateTime est une représentation immuable d'une date-heure avec un décalage. Cette classe stocke tous les champs de date et d’heure, avec une précision de nanosecondes, ainsi que le décalage par rapport à UTC / Greenwich.

L'instanceOffSetDateTime peut être créée comme ci-dessous en utilisantZoneOffset. Ici, nous créons unLocalDateTime représentant 6h30 le 20 février 2015:

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);

Ensuite, nous ajoutons deux heures à l'heure en créant unZoneOffset et en définissant pour l'instancelocalDateTime:

ZoneOffset offset = ZoneOffset.of("+02:00");

OffsetDateTime offSetByTwo = OffsetDateTime
  .of(localDateTime, offset);

Nous avons maintenant unlocalDateTime du 20/02/2015 06:30 +02: 00. Voyons maintenant comment modifier les valeurs de date et d'heure à l'aide des classesPeriod etDuration.

5. Utilisation dePeriod etDuration

La classePeriod représente une quantité de temps en termes d'années, de mois et de jours et la classeDuration représente une quantité de temps en termes de secondes et nano secondes.

5.1. Travailler avecPeriod

La classePeriod est largement utilisée pour modifier les valeurs d'une date donnée ou pour obtenir la différence entre deux dates:

LocalDate initialDate = LocalDate.parse("2007-05-10");

LesDate peuvent être manipulés à l'aide dePeriod comme indiqué dans l'extrait de code suivant:

LocalDate finalDate = initialDate.plus(Period.ofDays(5));

La classePeriod dispose de diverses méthodes getter telles quegetYears, getMonths etgetDays pour obtenir des valeurs d'un objetPeriod. L'exemple de code ci-dessous renvoie une valeurint de 5 lorsque nous essayons d'obtenir une différence en termes de jours:

int five = Period.between(initialDate, finalDate).getDays();

LesPeriod entre deux dates peuvent être obtenus dans une unité spécifique telle que jours ou mois ou années, en utilisantChronoUnit.between:

long five = ChronoUnit.DAYS.between(initialDate, finalDate);

Cet exemple de code retourne cinq jours. Continuons en jetant un œil à la classeDuration.

5.2. Travailler avecDuration

Similaire àPeriod,, leDuration class est utilisé pour traiterTime. Dans le code suivant, nous créons unLocalTime de 6h30 puis ajoutons une durée de 30 secondes pour faire unLocalTime de 06h30: 30h00:

LocalTime initialTime = LocalTime.of(6, 30, 0);

LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));

LesDuration entre deux instants peuvent être obtenus soit enDuration, soit en tant qu'unité spécifique. Dans le premier extrait de code, nous utilisons la méthodebetween() de la classeDuration pour trouver la différence de temps entrefinalTime etinitialTime et renvoyer la différence en secondes:

long thirty = Duration.between(initialTime, finalTime).getSeconds();

Dans le deuxième exemple, nous utilisons la méthodebetween() de la classeChronoUnit pour effectuer la même opération:

long thirty = ChronoUnit.SECONDS.between(initialTime, finalTime);

Nous allons maintenant voir comment convertir lesDate etCalendar existants en nouveauxDate /Time.

6. Compatibilité avecDate etCalendar

Java 8 a ajouté la méthodetoInstant() qui permet de convertir les instancesDate etCalendar existantes en une nouvelle API Date Time comme dans l'extrait de code suivant:

LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());

LesLocalDateTime peuvent être construits à partir des secondes d'époque comme ci-dessous. Le résultat du code ci-dessous serait unLocalDateTime représentant 2016-06-13T11: 34: 50:

LocalDateTime.ofEpochSecond(1465817690, 0, ZoneOffset.UTC);

Passons maintenant au formatageDate etTime.

7. Formatage deDate etTime

Java 8 fournit des API pour le formatage facile deDate etTime: __

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.JANUARY, 25, 6, 30);

Le code ci-dessous passe un format de date ISO pour formater la date locale. Le résultat serait 2015-01-25:

String localDateString = localDateTime.format(DateTimeFormatter.ISO_DATE);

LeDateTimeFormatter fournit diverses options de formatage standard. Des modèles personnalisés peuvent également être fournis pour formater la méthode, comme ci-dessous, qui renverrait unLocalDate comme 2015/01/25:

localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));

Nous pouvons passer le style de formatage soit enSHORT,LONG ouMEDIUM dans le cadre de l'option de formatage. L'exemple de code ci-dessous donnerait une sortie représentantLocalDateTime dans 25-Jan-2015, 06:30:00:

localDateTime
  .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))
  .withLocale(Locale.UK);

Jetons un coup d'œil aux alternatives disponibles pour les API Java 8 CoreDate /Time.

8. Backport et autres options

8.1. Utilisation du projet Threeten

Pour les organisations qui sont sur le point de passer à Java 8 à partir de Java 7 ou Java 6 et qui souhaitent utiliser l'API de date et d'heure, le projetthreeten fournit la capacité de rétroportage. Les développeurs peuvent utiliser les classes disponibles dans ce projet pour obtenir les mêmes fonctionnalités que celles des nouvelles API Java 8Date etTime et une fois qu'ils sont passés à Java 8, les packages peuvent être commutés. L'artefact pour le projet trois peut être trouvé dans lesmaven central repository:


    org.threeten
    threetenbp
    1.3.1

8.2. Bibliothèque Joda-Time

Une autre alternative pour la bibliothèque Java 8Date etTime est la bibliothèqueJoda-Time. En fait, les API Java 8Date Timeont été dirigées conjointement par l'auteur de la bibliothèque Joda-Time (Stephen Colebourne) et Oracle. Cette bibliothèque fournit à peu près toutes les fonctionnalités prises en charge dans le projet Java 8Date Time. L'Artefact peut être trouvé dans lesmaven central en incluant la dépendance pom ci-dessous dans votre projet:


    joda-time
    joda-time
    2.9.4

9. Conclusion

Java 8 fournit un ensemble complet d'API avec une conception cohérente pour un développement plus facile.

Les exemples de code pour l'article ci-dessus se trouvent dans le référentielJava 8 Date/Time git.