Classe Java ZonedDateTime

ZonedDateTime est une classe importante de l'API de date et d'heure (paquet java.time) introduite dans Java 8 ; elle représente une date et une heure avec un fuseau horaire. Cette classe combine LocalDateTime et ZoneId pour représenter précisément un instant dans un fuseau horaire spécifique.

Fonctionnalités principales

  • Contient la date (année, mois, jour)
  • Contient l'heure (heure, minute, seconde, nanoseconde)
  • Contient les informations de fuseau horaire
  • Est une classe immuable et sûre pour les threads
  • Prend en charge la conversion de fuseau horaire et l'ajustement automatique de l'heure d'été

Façons de créer ZonedDateTime

1. Création avec l'heure actuelle

Exemple

// Obtenir la date et l'heure actuelles dans le fuseau horaire par défaut du système
ZonedDateTime now = ZonedDateTime.now();

// Obtenir la date et l'heure actuelles dans le fuseau horaire spécifié
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

2. Création à partir de composants

Exemple

// Spécifier l'année, le mois, le jour, l'heure, la minute, la seconde et le fuseau horaire
ZonedDateTime customDateTime = ZonedDateTime.of(
    2023, 12, 25, 15, 30, 0, 0,
    ZoneId.of("America/New_York")
);

3. Combinaison de LocalDateTime et ZoneId

Exemple

LocalDateTime localDateTime = LocalDateTime.of(2023, 6, 15, 10, 30);
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime parisTime = ZonedDateTime.of(localDateTime, zoneId);

Méthodes d'opérations courantes

1. Obtention d'informations temporelles

Exemple

ZonedDateTime zdt = ZonedDateTime.now();

int year = zdt.getYear();          // Année
Month month = zdt.getMonth();      // Mois
int day = zdt.getDayOfMonth();     // Jour
int hour = zdt.getHour();          // Heure
int minute = zdt.getMinute();      // Minute
int second = zdt.getSecond();      // Seconde
ZoneId zone = zdt.getZone();       // Fuseau horaire

2. Ajout et soustraction de temps

Exemple

ZonedDateTime zdt = ZonedDateTime.now();

// Ajouter 1 jour
ZonedDateTime tomorrow = zdt.plusDays(1);

// Soustraire 2 heures
ZonedDateTime twoHoursEarlier = zdt.minusHours(2);

// Ajouter 3 semaines
ZonedDateTime threeWeeksLater = zdt.plusWeeks(3);

3. Conversion de fuseau horaire

Exemple

ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

// Convertir en heure de New York
ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));

// Convertir en heure UTC
ZonedDateTime utcTime = tokyoTime.withZoneSameInstant(ZoneOffset.UTC);

Exemples d'applications pratiques

1. Calcul du décalage horaire entre deux fuseaux horaires

Exemple

ZonedDateTime londonTime = ZonedDateTime.now(ZoneId.of("Europe/London"));
ZonedDateTime sydneyTime = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));

// Calculer la différence en heures
long hoursBetween = ChronoUnit.HOURS.between(londonTime, sydneyTime);
System.out.println("Décalage horaire actuel entre Londres et Sydney : " + hoursBetween + "heures");

2. Gestion des horaires de réunion entre fuseaux horaires

Exemple

// L'heure de la réunion à New York est 3 PM
ZonedDateTime meetingTimeNY = ZonedDateTime.of(
    LocalDate.now(),
    LocalTime.of(15, 0),
    ZoneId.of("America/New_York")
);

// Convertir en heure de Tokyo
ZonedDateTime meetingTimeTokyo = meetingTimeNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println("Les participants de Tokyo devraient y être à l'heure locale : " + meetingTimeTokyo);

3. Gestion de l'heure d'été

Exemple

// Heures avant et après le passage à l'heure d'été à New York
ZonedDateTime beforeDST = ZonedDateTime.of(
    LocalDateTime.of(2023, 3, 11, 1, 30),
    ZoneId.of("America/New_York")
);

ZonedDateTime afterDST = beforeDST.plusHours(1);
System.out.println("Différence horaire réelle : " +
    Duration.between(beforeDST, afterDST).toHours() + "hours");

Conversion de ZonedDateTime et d'autres classes de date-heure

1. Conversion en Instant

Exemple

ZonedDateTime zdt = ZonedDateTime.now();
Instant instant = zdt.toInstant();  // Convertir en horodatage UTC

2. Conversion en LocalDateTime

Exemple

ZonedDateTime zdt = ZonedDateTime.now();
LocalDateTime ldt = zdt.toLocalDateTime();  // Perd les informations de fuseau horaire

3. Création à partir d'Instant

Exemple

Instant instant = Instant.now();
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));

Exemple complet

Exemple

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class ZonedDateTimeDemo {
    public static void main(String[] args) {
        // 1. Obtenir l'heure actuelle dans le fuseau horaire actuel
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println("Heure du fuseau horaire actuel : " + now);
       
        // 2. Obtenir l'heure actuelle dans le fuseau horaire spécifié
        ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
        System.out.println("Heure de Tokyo : " + tokyoTime);
       
        // 3. Créer une date-heure spécifique avec un fuseau horaire
        ZonedDateTime specificTime = ZonedDateTime.of(
            2023, 5, 15, 10, 30, 0, 0,
            ZoneId.of("America/New_York")
        );
        System.out.println("Heure spécifique à New York : " + specificTime);
       
        // 4. Conversion de fuseau horaire
        ZonedDateTime londonTime = specificTime.withZoneSameInstant(ZoneId.of("Europe/London"));
        System.out.println("Heure correspondante à Londres : " + londonTime);
       
        // 5. Formatage de la sortie
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
        System.out.println("Heure formatée : " + now.format(formatter));
       
        // 6. Obtenir des informations pour chaque composant
        System.out.println("Fuseau horaire : " + now.getZone());
        System.out.println("Année : " + now.getYear());
        System.out.println("Mois : " + now.getMonth());
        System.out.println("Heure : " + now.getHour());
    }
}

La sortie est similaire à ce qui suit :

当前时区时间: 2025-05-01T11:29:07.411467+08:00[Asia/Shanghai]
东京时间: 2025-05-01T12:29:07.417938+09:00[Asia/Tokyo]
纽约特定时间: 2023-05-15T10:30-04:00[America/New_York]
对应的伦敦时间: 2023-05-15T15:30+01:00[Europe/London]
格式化时间: 2025-05-01 11:29:07 CST
时区: Asia/Shanghai
年份: 2025
月份: MAY
小时: 11

Bonnes pratiques

  1. Stockage et transmission: Lors du stockage dans une base de données ou de la transmission sur un réseau, il est recommandé d'utiliser Instant ou ZonedDateTime en UTC
  2. Affichage: Convertir vers le fuseau horaire local uniquement lors de l'affichage dans l'interface utilisateur
  3. Comparaison: Lors de la comparaison de moments dans des fuseaux horaires différents, convertissez-les d'abord dans le même fuseau horaire ou en Instant
  4. Heure d'été: Utilisez toujours l'ID complet du fuseau horaire (par ex. "America/New_York") au lieu d'un simple décalage (par ex. "-05:00")

ZonedDateTime est un outil puissant pour gérer les applications sensibles aux fuseaux horaires ; une utilisation correcte permet d'éviter de nombreux problèmes courants de date-heure.

Méthodes de fabrique statiques

Méthode Description Exemple
static ZonedDateTime now() Obtenir la date-heure actuelle dans le fuseau horaire actuel ZonedDateTime.now()
static ZonedDateTime now(ZoneId zone) Obtenir la date-heure actuelle dans le fuseau horaire spécifié ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))
static ZonedDateTime of(int year, int month, int day, int hour, int minute, int second, int nano, ZoneId zone) Créer avec des paramètres spécifiés ZonedDateTime.of(2023, 6, 15, 14, 30, 0, 0, ZoneId.of("GMT+8"))
static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) Créer en combinant LocalDate, LocalTime et le fuseau horaire ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault())
static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone) Créer à partir de LocalDateTime et du fuseau horaire ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("America/New_York"))
static ZonedDateTime ofInstant(Instant instant, ZoneId zone) Créer à partir d'Instant et du fuseau horaire ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC"))
static ZonedDateTime parse(CharSequence text) Analyser à partir d'une chaîne ZonedDateTime.parse("2023-06-15T14:30:45+08:00[Asia/Shanghai]")
static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) Analyser en utilisant un format spécifié ZonedDateTime.parse("2023-06-15 14:30 CST", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z"))

Obtenir des informations sur la date et l'heure

Méthode Description Exemple
int getYear() Obtenir l'année 2023
Month getMonth() Obtenir le mois (énumération Month) Month.JUNE
int getMonthValue() Obtenir la valeur du mois (1-12) 6
int getDayOfMonth() Obtenir le jour du mois 15
int getDayOfYear() Obtenir le jour de l'année 166
DayOfWeek getDayOfWeek() Obtenir le jour de la semaine (énumération DayOfWeek) DayOfWeek.THURSDAY
int getHour() Obtenir l'heure (0-23) 14
int getMinute() Obtenir les minutes (0-59) 30
int getSecond() Obtenir la seconde (0-59) 45
int getNano() Obtenir la nanoseconde 0
ZoneId getZone() Obtenir le fuseau horaire Asia/Shanghai
ZoneOffset getOffset() Obtenir le décalage de fuseau horaire +08:00

Opérations sur la date et l'heure

Méthode Description Exemple
ZonedDateTime plusDays(long days) Ajouter des jours zdt.plusDays(5)
ZonedDateTime plusHours(long hours) Ajouter des heures zdt.plusHours(2)
ZonedDateTime plusMinutes(long minutes) Ajouter des minutes zdt.plusMinutes(30)
ZonedDateTime plusSeconds(long seconds) Ajouter des secondes zdt.plusSeconds(45)
ZonedDateTime plusNanos(long nanos) Ajouter des nanosecondes zdt.plusNanos(1000000)
ZonedDateTime minusDays(long days) Soustraire des jours zdt.minusDays(5)
ZonedDateTime minusHours(long hours) Soustraire des heures zdt.minusHours(2)
ZonedDateTime minusMinutes(long minutes) Soustraire des minutes zdt.minusMinutes(30)
ZonedDateTime minusSeconds(long seconds) Soustraire des secondes zdt.minusSeconds(45)
ZonedDateTime minusNanos(long nanos) Soustraire des nanosecondes zdt.minusNanos(1000000)
ZonedDateTime withYear(int year) Modifier l'année zdt.withYear(2024)
ZonedDateTime withMonth(int month) Modifier le mois zdt.withMonth(12)
ZonedDateTime withDayOfMonth(int day) Modifier le jour du mois zdt.withDayOfMonth(1)
ZonedDateTime withHour(int hour) Modifier l'heure zdt.withHour(0)
ZonedDateTime withMinute(int minute) Modifier la minute zdt.withMinute(0)
ZonedDateTime withSecond(int second) Modifier la seconde zdt.withSecond(0)
ZonedDateTime withNano(int nano) Modifier la nanoseconde zdt.withNano(0)
ZonedDateTime withZoneSameInstant(ZoneId zone) Convertir le fuseau horaire (en conservant le même instant) zdt.withZoneSameInstant(ZoneId.of("UTC"))
ZonedDateTime withZoneSameLocal(ZoneId zone) Convertir le fuseau horaire (en conservant l'heure locale) zdt.withZoneSameLocal(ZoneId.of("UTC"))

Méthodes de conversion

Méthode Description Exemple
LocalDate toLocalDate() Convertir en LocalDate zdt.toLocalDate()
LocalTime toLocalTime() Convertir en LocalTime zdt.toLocalTime()
LocalDateTime toLocalDateTime() Convertir en LocalDateTime zdt.toLocalDateTime()
OffsetDateTime toOffsetDateTime() Convertir en OffsetDateTime zdt.toOffsetDateTime()
Instant toInstant() Convertir en Instant zdt.toInstant()

Méthodes de comparaison

Méthode Description Exemple
boolean isAfter(ChronoZonedDateTime<?> other) Indique si c'est après la date-heure spécifiée zdt1.isAfter(zdt2)
boolean isBefore(ChronoZonedDateTime<?> other) Indique si c'est avant la date-heure spécifiée zdt1.isBefore(zdt2)
boolean isEqual(ChronoZonedDateTime<?> other) Indique si c'est égal à la date-heure spécifiée zdt1.isEqual(zdt2)
int compareTo(ChronoZonedDateTime<?> other) Comparer deux date-heures zdt1.compareTo(zdt2)

Formatage et conversion en chaîne

Méthodes Description Exemple
String format(DateTimeFormatter formatter) Formater en chaîne zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)
String toString() Convertir en chaîne au format ISO "2023-06-15T14:30:45+08:00[Asia/Shanghai]"
Autres extensions