Fuseaux horaires en Java : comment ne pas perdre la tête et ne pas rater son deadline

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi le temps en Java est une douleur (et comment la soigner)

\n

Chaque développeur qui a ne serait-ce qu'une fois été confronté à des tâches de globalisation d'application le sait : travailler avec les fuseaux horaires est un champ de mines. Quoi de plus simple, semble-t-il ? On prend une date, on la convertit dans un autre fuseau horaire, et voilà. Mais non. Les anciennes API comme java.util.Date et java.util.Calendar laissaient derrière elles une multitude de bugs, une confusion avec l'heure d'été et des cheveux blancs.

\n

Heureusement, avec la sortie de Java 8, le monde a changé. Le nouveau package java.time (JSR-310) a apporté ordre et clarté. Aujourd'hui, nous allons voir comment travailler correctement avec les fuseaux horaires en Java moderne, éviter les pièges typiques et rendre le code lisible et fiable.

\n

Si vous codez en Java et que votre application travaille avec des utilisateurs de différents pays, cet article est pour vous. C'est parti !

\n\n

Découverte de la nouvelle API : java.time

\n

Avant de plonger dans les détails, familiarisons-nous avec les classes clés. Elles ne sont pas nombreuses et chacune a son rôle.

\n\n

LocalDateTime — l'heure sans lien avec un fuseau

\n

Cette classe stocke la date et l'heure, mais ne tient pas compte du fuseau horaire. Elle est pratique pour enregistrer des événements qui se produisent au même endroit (par exemple, des logs sur un serveur).

\n
LocalDateTime local = LocalDateTime.now();\nSystem.out.println(local); // 2025-03-15T14:30:00.123
\n

Mais si vous essayez d'envoyer cette heure à un utilisateur à New York alors que votre serveur est à Moscou, vous créerez de la confusion. C'est pourquoi les systèmes globaux nécessitent d'autres outils.

\n\n

ZonedDateTime — l'heure avec toutes les informations de fuseau

\n

C'est le « standard en or » pour travailler avec les fuseaux horaires en Java. Il stocke la date, l'heure et l'identifiant du fuseau horaire (ZoneId). C'est cette classe qu'il faut utiliser lorsque vous voulez savoir précisément dans quel fuseau se trouve un événement.

\n
ZonedDateTime nowInMoscow = ZonedDateTime.now(ZoneId.of("Europe/Moscow"));\nSystem.out.println(nowInMoscow); // 2025-03-15T14:30+03:00[Europe/Moscow]
\n\n

OffsetDateTime — l'heure avec un décalage

\n

Semblable à ZonedDateTime, mais ne stocke que le décalage par rapport à UTC (par exemple, +03:00), sans le nom de la région. Utile pour les API où seule la différence avec Greenwich compte.

\n\n

Instant — un moment dans le temps en UTC

\n

Un format lisible par machine. Instant est un point sur la ligne du temps, toujours en UTC. Idéal pour le stockage dans les bases de données et les échanges entre services.

\n
Instant instant = Instant.now();\nSystem.out.println(instant); // 2025-03-15T11:30:00.123Z
\n\n

Comment bien choisir son fuseau horaire : ZoneId

\n

N'utilisez pas d'abréviations à trois lettres comme "PST" ou "CET" — elles sont ambiguës et ne tiennent pas compte de l'heure d'été. Préférez les identifiants complets de la base de données IANA (Time Zone Database).

\n

Exemples de ZoneId corrects :

\n
    \n
  • "Europe/Moscow"
  • \n
  • "America/New_York"
  • \n
  • "Asia/Tokyo"
  • \n
  • "UTC"
  • \n
\n

Obtenir tous les fuseaux disponibles se fait ainsi :

\n
Set<String> zoneIds = ZoneId.getAvailableZoneIds();\nzoneIds.stream().sorted().limit(10).forEach(System.out::println);
\n\n

Conversion entre fuseaux horaires : exemples pratiques

\n

La tâche la plus courante est de prendre une heure dans un fuseau et de l'afficher à l'utilisateur dans un autre. Cela se fait très simplement.

\n\n

Exemple 1 : Convertir l'heure de Moscou à New York

\n
ZonedDateTime moscowTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"));\nZonedDateTime newYorkTime = moscowTime.withZoneSameInstant(ZoneId.of("America/New_York"));\n\nSystem.out.println("Moscou : " + moscowTime);\nSystem.out.println("New York : " + newYorkTime);
\n

Notez la méthode withZoneSameInstant() — elle change uniquement l'affichage de l'heure, tout en conservant le moment physique.

\n\n

Exemple 2 : De l'UTC à l'heure locale de l'utilisateur

\n

Blogs

Book Recommendations