CodeGym /Cours /JAVA 25 SELF /Aperçu de l’API java.time, différences avec les anciennes...

Aperçu de l’API java.time, différences avec les anciennes API

JAVA 25 SELF
Niveau 13, Leçon 1
Disponible

1. Contexte historique : comment on travaillait avec les dates avant Java 8

Dans un lointain passé (avant Java 8), on utilisait les classes java.util.Date, java.util.Calendar et pour le formatage — java.text.SimpleDateFormat. C’était l’un de ces cas où les programmeurs du monde entier soupiraient à l’unisson et, en grinçant des dents, écrivaient quelque chose comme :

import java.util.Date;

Date now = new Date();
System.out.println(now); // Affichera quelque chose d'étrange comme "Wed Jun 05 14:15:22 MSK 2025"

Ça a l’air simple, mais en pratique tout n’était pas si rose. Voici seulement quelques « joies » de l’ancien API :

  • Date — un objet mutable. On pouvait le modifier par inadvertance, ce qui menait souvent à des bugs.
  • Les mois dans Date et Calendar commençaient à zéro (janvier — c’est 0, décembre — 11), alors que les jours commençaient à un.
  • SimpleDateFormat n’était pas thread-safe : si deux threads formataient une date simultanément, on pouvait obtenir des résultats inattendus.
  • Une énorme quantité de méthodes étaient annotées @Deprecated (obsolètes), et l’IDE vous bombardait constamment d’avertissements jaunes.
  • La gestion des fuseaux horaires était une vraie douleur : il était facile de confondre l’heure locale et l’UTC, et mieux valait ne pas penser aux changements heure d’été/hiver.

Exemple douloureux

import java.util.Date;

Date date = new Date(2025, 5, 1); // année 2025, mois 5 (juin ?), jour 1
System.out.println(date); // Pas ce à quoi vous vous attendez !

2. Apparition de java.time : une nouvelle approche

Vers 2014, il est devenu clair que l’ancien API n’était pas seulement peu pratique — il était dangereux. C’est pourquoi un nouveau package est apparu dans Java — java.time, implémentant la spécification JSR‑310. Cet API a été inspiré par la bibliothèque populaire Joda-Time et est devenu immédiatement un standard de facto.

Paquets et classes principaux

  • java.time — le package principal, où vivent toutes les nouvelles classes de date et d’heure.
  • java.time.format — pour le formatage et l’analyse des dates et des heures.
  • java.time.temporal — pour des opérations temporelles plus avancées.
  • java.time.zone — pour travailler avec les fuseaux horaires.

Voici les principaux protagonistes du nouvel API :

Classe À quoi ça sert ? Exemple d’utilisation
LocalDate
Date seule (année, mois, jour) Anniversaire, sans heure
LocalTime
Heure seule (heures, minutes, secondes) Heure d’un rendez-vous, sans date
LocalDateTime
Date et heure, sans fuseau horaire Événement local
ZonedDateTime
Date et heure avec fuseau horaire Réunion à Minsk à l’heure locale
Instant
Instant absolu (UTC) Horodatage dans un journal
Duration
Intervalle de temps (heures, minutes, s) Durée d’un appel
Period
Période (années, mois, jours) Ancienneté, âge

Exemple : création d’une date, nouvelle manière

import java.time.LocalDate;

LocalDate today = LocalDate.now();
System.out.println(today); // Par exemple, "2025-06-05"

3. Avantages du nouvel API

Immuabilité (immutable)

Toutes les classes de java.time sont immuables. Cela signifie : si vous créez un objet LocalDate, vous ne pouvez pas le modifier. Toute opération (par exemple, ajouter un jour) renvoie un nouvel objet.

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

System.out.println(today);    // 2025-06-05
System.out.println(tomorrow); // 2025-06-06

Gestion explicite des fuseaux horaires

Dans l’ancien API, il était facile d’oublier dans quel fuseau horaire se trouvait la date. Avec java.time, tout est explicite : si vous avez besoin d’un fuseau horaire — utilisez ZonedDateTime, si ce n’est pas nécessaire — utilisez LocalDateTime.

import java.time.ZonedDateTime;
import java.time.ZoneId;

ZonedDateTime MinskTime = ZonedDateTime.now(ZoneId.of("Europe/Minsk"));
System.out.println(MinskTime); // 2025-06-05T14:23:45+03:00[Europe/Minsk]

Méthodes pratiques pour les calculs et les comparaisons

LocalDate today = LocalDate.now();
LocalDate nextMonth = today.plusMonths(1);
boolean isAfter = LocalDate.now().plusDays(1).isAfter(today); // true

Formatage et analyse

Le formatage et l’analyse — via DateTimeFormatter (détails — à la prochaine leçon) :

import java.time.format.DateTimeFormatter;

LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
String formatted = today.format(formatter); // "05.08.2025"

4. Compatibilité : comment vivre avec l’ancien code

Dans le monde réel, il faut très souvent travailler avec des bibliothèques ou des systèmes anciens qui utilisent Date et Calendar. Heureusement, le nouvel API est amical avec l’héritage : on peut convertir les anciens types en nouveaux et inversement.

Conversion Date ↔ Instant

import java.util.Date;
import java.time.Instant;

// Date → Instant
Date legacyDate = new Date();
Instant instant = legacyDate.toInstant();

// Instant → Date
Date dateBack = Date.from(instant);

Conversion Calendar ↔ ZonedDateTime

import java.util.Calendar;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.util.Date;

// Calendar → ZonedDateTime
Calendar calendar = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(
        calendar.toInstant(),
        calendar.getTimeZone().toZoneId()
);

// ZonedDateTime → Calendar
Calendar calBack = Calendar.getInstance();
calBack.setTime(Date.from(zdt.toInstant()));

Tableau : correspondance des anciennes et des nouvelles classes

Ancienne classe Nouvelle classe Commentaire
java.util.Date
Instant
Temps absolu
java.util.Calendar
ZonedDateTime
Date et heure avec fuseau horaire
java.text.SimpleDateFormat
DateTimeFormatter
Formatage/analyse des dates

5. Pratique : premiers pas avec java.time

Supposons que vous ayez un utilisateur avec une date de naissance. Enregistrons et affichons cette date :

import java.time.LocalDate;

public class UserProfile {
    private String name;
    private LocalDate birthDate;

    public UserProfile(String name, LocalDate birthDate) {
        this.name = name;
        this.birthDate = birthDate;
    }

    public void printProfile() {
        System.out.println("Nom: " + name);
        System.out.println("Date de naissance: " + birthDate);
    }
}

public class Main {
    public static void main(String[] args) {
        UserProfile user = new UserProfile("Alisa", LocalDate.of(1998, 12, 25));
        user.printProfile();
    }
}

Sortie :

Nom: Alisa
Date de naissance: 1998-12-25

6. Comparaison : ancien API vs nouvel API

Exemple : ajouter une semaine à la date de naissance

Ancienne méthode (Date/Calendar) :

import java.util.Calendar;

Calendar cal = Calendar.getInstance();
cal.set(1998, Calendar.DECEMBER, 25);
cal.add(Calendar.WEEK_OF_YEAR, 1);
System.out.println(cal.getTime()); // Laborieux et peu évident

Nouvelle méthode (java.time) :

import java.time.LocalDate;

LocalDate birthDate = LocalDate.of(1998, 12, 25);
LocalDate nextWeek = birthDate.plusWeeks(1);
System.out.println(nextWeek); // 1999-01-01

Avec le nouvel API, le code est plus court, plus simple et plus sûr.

7. Erreurs courantes avec java.time

Erreur n°1 : oublier que les objets sont immuables.
Si vous appelez date.plusDays(1); sans conserver le résultat, la date initiale restera inchangée.

Erreur n°2 : confusion entre LocalDate et LocalDateTime.
LocalDate ne stocke que la date (année, mois, jour), tandis que LocalDateTime stocke aussi l’heure. Ne les confondez pas si vous devez gérer les heures et les minutes.

Erreur n°3 : utiliser les anciennes classes dans de nouveaux projets.
Si possible — utilisez toujours java.time. Les anciennes classes ne sont nécessaires que pour la compatibilité.

Erreur n°4 : mauvaise gestion des fuseaux horaires.
Si vous devez stocker un événement pertinent pour différentes régions, utilisez ZonedDateTime ou au moins Instant. LocalDateTime ne contient pas d’information de fuseau horaire !

Erreur n°5 : tenter de comparer directement LocalDate et LocalDateTime.
Ce sont des types de données différents, on ne peut pas les comparer directement. Commencez par les ramener à un même type.

1
Mission
JAVA 25 SELF, niveau 13, leçon 1
Bloqué
Marquer la date du jour dans le calendrier 🗓️
Marquer la date du jour dans le calendrier 🗓️
1
Mission
JAVA 25 SELF, niveau 13, leçon 1
Bloqué
Regard en arrière : quel jour était hier ? ⏪
Regard en arrière : quel jour était hier ? ⏪
1
Mission
JAVA 25 SELF, niveau 13, leçon 1
Bloqué
Regardons l'avenir: quel jour sera demain? ⏩
Regardons l'avenir: quel jour sera demain? ⏩
1
Mission
JAVA 25 SELF, niveau 13, leçon 1
Bloqué
Enregistrement d'un moment historique important 📜
Enregistrement d'un moment historique important 📜
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION