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"));
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")
);
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);
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
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);
// 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);
// 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");
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);
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");
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
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
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"));
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());
}
}
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
- 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
- Affichage: Convertir vers le fuseau horaire local uniquement lors de l'affichage dans l'interface utilisateur
- 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
- 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]" |