devstory

Le Tutoriel de Java ZonedDateTime

  1. ZonedDateTime
  2. ZonedDateTime prend en charge les données historiques
  3. ZonedDateTime & DST
  4. ZonedDateTime methods
  5. withZoneSameInstant(ZoneId)
  6. withZoneSameLocal(ZoneId)
  7. withEarlierOffsetAtOverlap()
  8. withLaterOffsetAtOverlap()
  9. withFixedOffsetZone()

1. ZonedDateTime

ZonedDateTime est une classe représentant la date et l'heure avec des informations de fuseau horaire, située dans le système de calendrier ISO-8601, tel que 2007-12-03T10:15:30":" Europe/Paris.
La classe ZonedDateTime se situe dans le package java.time. Comme toutes les classes fournies par Java Date Time API, ZonedDateTime est immuable, ce qui signifie que tous les calculs dans ZonedDateTime créent un nouvel objet ZonedDateTime, il peut donc être utilisé en toute sécurité dans un environnement multithreading.
Avant de continuer, il est nécessaire d'en savoir plus sur les concepts GMT, UTC et UT :
  • GMT vs UTC
public final class ZonedDateTime
        implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {

    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
    private final ZoneId zone;
}
En regardant le code source de la classe ZonedDateTime, on voit qu'elle gère 3 objets internes, dont :
  • L'objet LocalDateTime contient des informations de date et d'heure.
  • L'objet ZoneId est le nom d'identifiant du fuseau horaire, tel que Europe/Paris.
  • L'objet ZoneOffset contient des informations de décalage de fuseau horaire, telles que +01:30.
Par exemple : Avec un objet LocalDateTime contenant uniquement des informations de date et d'heure, on ajoute des informations de fuseau horaire pour créer un objet ZonedDateTime contenant des informations de date, d'heure et de fuseau horaire.
ZonedDateTimeEx1.java
package org.o7planning.zoneddatetime.ex;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class ZonedDateTimeEx1 {

    public static void main(String[] args) {
        // LocalDateTime:
        LocalDateTime myLocalDateTime = LocalDateTime.of(2020, Month.MAY, 15, 13, 45, 30);

        System.out.println("My LocalDateTime: " + myLocalDateTime); // 2020-05-15T13:45:30

        // UTC+7 (Ho Chi Minh Vietnam).
        ZoneId vnZoneId = ZoneId.of("Asia/Ho_Chi_Minh");

        // Add time zone information to LocalDateTime.
        ZonedDateTime vnDateTime = ZonedDateTime.of(myLocalDateTime, vnZoneId);

        System.out.println("VN DateTime: " + vnDateTime); // 2020-05-15T13:45:30+07:00[Asia/Ho_Chi_Minh]

        // Same as:
        ZonedDateTime vnDateTime2 = myLocalDateTime.atZone(vnZoneId);

        System.out.println("VN DateTime: " + vnDateTime2); // 2020-05-15T13:45:30+07:00[Asia/Ho_Chi_Minh]
    }
}
Output:
My LocalDateTime: 2020-05-15T13:45:30
VN DateTime: 2020-05-15T13:45:30+07:00[Asia/Ho_Chi_Minh]
VN DateTime: 2020-05-15T13:45:30+07:00[Asia/Ho_Chi_Minh]
Par exemple : A quelle heure correspond au réveillon du Nouvel An 2020 au Vietnam, au Japon et en France ? L'exemple suivant vous montrera une telle conversion de temps :
ZonedDateTimeEx2.java
// 2000-01-01 00:00:00
LocalDateTime localDateTime = LocalDateTime.of(2000, Month.JANUARY, 1, 0, 0, 0);

System.out.println("LocalDateTime: " + localDateTime); // 2000-01-01T00:00
System.out.println();

// UTC+7 (Ho Chi Minh Vietnam).
ZoneId vnZoneId = ZoneId.of("Asia/Ho_Chi_Minh");
// Add time zone to it!
ZonedDateTime vnDateTime = ZonedDateTime.of(localDateTime, vnZoneId);

System.out.println("Vietnam: " + vnDateTime); // 2000-01-01T00:00+07:00[Asia/Ho_Chi_Minh]

// UTC+9 (Tokyo Japan).
ZoneId jpZoneId = ZoneId.of("Asia/Tokyo");
ZonedDateTime jpDateTime = vnDateTime.withZoneSameInstant(jpZoneId);

System.out.println("Japan: " + jpDateTime); // 2000-01-01T02:00+09:00[Asia/Tokyo]

// UTC+1 (Paris France).
ZoneId frZoneId = ZoneId.of("Europe/Paris");
ZonedDateTime frDateTime = vnDateTime.withZoneSameInstant(frZoneId);

System.out.println("France: " + frDateTime); // 1999-12-31T18:00+01:00[Europe/Paris]
Output:
LocalDateTime: 2000-01-01T00:00

Vietnam: 2000-01-01T00:00+07:00[Asia/Ho_Chi_Minh]
Japan: 2000-01-01T02:00+09:00[Asia/Tokyo]
France: 1999-12-31T18:00+01:00[Europe/Paris]
Par exemple : A 12 heures le 1er janvier 2020, vous volez du Vietnam au Japon. La durée du vol est de 6 heures 15 minutes. La question est à quelle heure arriverez-vous au Japon ?
ZonedDateTime_flight_ex1.java
// 2020-01-01 12:00:00
LocalDateTime localDateTime = LocalDateTime.of(2020, Month.JANUARY, 1, 12, 0, 0);

System.out.println("LocalDateTime: " + localDateTime); // 2020-01-01T12:00
System.out.println();

// UTC+7 (Ho Chi Minh Vietnam).
ZoneId vnZoneId = ZoneId.of("Asia/Ho_Chi_Minh");
// Add time zone to it!
ZonedDateTime vnDateTime = ZonedDateTime.of(localDateTime, vnZoneId);

System.out.println("Depart from Vietnam at: " + vnDateTime); // 2020-01-01T12:00+07:00[Asia/Ho_Chi_Minh]

// UTC+9 (Tokyo Japan).
ZoneId jpZoneId = ZoneId.of("Asia/Tokyo");
ZonedDateTime jpDateTime = vnDateTime.withZoneSameInstant(jpZoneId).plusHours(6).plusMinutes(15);

System.out.println("Arrive to Japan at: " + jpDateTime); // 2020-01-01T20:15+09:00[Asia/Tokyo]
Output:
LocalDateTime: 2020-01-01T12:00

Depart from Vietnam at: 2020-01-01T12:00+07:00[Asia/Ho_Chi_Minh]
Arrive to Japan at: 2020-01-01T20:15+09:00[Asia/Tokyo]

2. ZonedDateTime prend en charge les données historiques

Le fuseau horaire d'une zone géographique peut varier légèrement en raison des objectifs du pays et de l'emplacement géographique. Ce qui est intéressant, c'est que ZonedDateTime stocke ces données historiques. Par exemple, de 1960 jusqu'à avant le 13 juin 1975, le sud du Vietnam a utilisé le fuseau horaire UTC+8, puis est passé au fuseau horaire UTC+7 pour s'accorder avec le nord du pays.
Pour mieux comprendre, observer l'exemple ci-dessous :
ZonedDateTime_history_ex1.java
package org.o7planning.zoneddatetime.ex;

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

public class ZonedDateTime_history_ex1 {

    public static void main(String[] args) {
        // Time-zone Ho Chi Minh City (Vietnam).
        ZoneId hcmZoneId = ZoneId.of("Asia/Ho_Chi_Minh");

        // 1975-06-12 (UTC+8)
        ZonedDateTime zdt1 = ZonedDateTime.of(1975, 6, 12, 0, 0, 0, 0, hcmZoneId);
        System.out.println("zdt1: " + zdt1); // 1975-06-12T00:00+08:00[Asia/Ho_Chi_Minh]

        // 1975-06-13 (UTC+7)
        ZonedDateTime zdt2 = ZonedDateTime.of(1975, 6, 13, 0, 0, 0, 0, hcmZoneId);
        System.out.println("zdt2: " + zdt2); // 1975-06-13T00:00+07:00[Asia/Ho_Chi_Minh]
    }
}
Output:
zdt1: 1975-06-12T00:00+08:00[Asia/Ho_Chi_Minh]
zdt2: 1975-06-13T00:00+07:00[Asia/Ho_Chi_Minh]

3. ZonedDateTime & DST

Actuellement, aux États-Unis, beaucoup d'États appliquent l'heure d'été Daylight Saving Time (DST). Concrètement, de 14h du deuxième dimanche en mars à 14h du premier dimanche en novembre, les horloges seront avancés d'une heure.

United States

European Union
Year
DST Begins at 2 a.m.
DST Ends at 2 a.m.
Summertime period begins at 1 a.m. UT
Summertime period ends at 1 a.m. UT
2017
March 12
November 5
March 26
October 29
2018
March 11
November 4
March 25
October 28
2019
March 10
November 3
March 31
October 27
2020
March 8
November 1
March 29
October 25
2021
March 14
November 7
March 28
October 31
2022
March 13
November 6
March 27
October 30
2023
March 12
November 5
March 26
October 29
2024
March 10
November 3
March 31
October 27
En 2021, aux États-Unis, l'heure d'été DST commence à 02h00 le 14 mars et se termine à 02h00 le 7 novembre. Voir comment Java 8 Date Time API règle l'heure d'été DST.
On va créer un objet ZonedDateTime représentant 1h30 du matin le 14 mars 2021 dans le centre des États-Unis. Ajouter ensuite 1 heure et voir ce qui se passe.
ZonedDateTime_dst_ex1.java
package org.o7planning.zoneddatetime.ex;

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

public class ZonedDateTime_dst_ex1 {

    public static void main(String[] args) {
        // US/Central
        ZoneId uscZoneId = ZoneId.of("US/Central");

        //
        // Year 2021 in America:
        // DST begin at March 14 to November 7 (2021-03-14 02:00 --> 2021-11-07 02:00)
        //

        // 2021-03-14 (UTC-6)
        ZonedDateTime zdt1 = ZonedDateTime.of(2021, 3, 14, 1, 30, 0, 0, uscZoneId);
        System.out.println("zdt1: " + zdt1); // 2021-03-14T01:30-06:00[US/Central]

        // Add 1 Hour to zdt1
        ZonedDateTime zdt2 = zdt1.plusHours(1);
        System.out.println("zdt2: " + zdt2); // 2021-03-14T03:30-05:00[US/Central]
    }
}
Output:
zdt1: 2021-03-14T01:30-06:00[US/Central]
zdt2: 2021-03-14T03:30-05:00[US/Central]
Flight from Vietnam to France:
Par exemple : On suppose qu'à 12h00 le 1er mai 2021, vous preniez un vol au départ du Vietnam à destination de France, la durée du vol est de 13 heures et 6 minutes. Alors, à quelle heure arriverez-vous en France ?
Remarque : En 2021, l'heure d'été DST en France commence à 1h00 le 28 mars et termine à 1h00 le 31 octobre. Le fuseau horaire par défaut de France est UTC+1, alors que pendant la période d'heure d'été DST, le pays utilise le fuseau horaire UTC+2.
ZonedDateTime_flight_ex2.java
// 2020-01-01 12:00:00
LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MAY, 1, 12, 0, 0);
 
// UTC+7 (Ho Chi Minh Vietnam).
ZoneId vnZoneId = ZoneId.of("Asia/Ho_Chi_Minh");
// Add time zone to it!
ZonedDateTime vnDateTime = ZonedDateTime.of(localDateTime, vnZoneId);

System.out.println("Depart from Vietnam at: " + vnDateTime); // 2021-05-01T12:00+07:00[Asia/Ho_Chi_Minh]

// Europe/Paris: Default offset: +1. DST offset: +2
ZoneId frZoneId = ZoneId.of("Europe/Paris");
ZonedDateTime frDateTime = vnDateTime.withZoneSameInstant(frZoneId).plusHours(13).plusMinutes(6);

System.out.println("Arrive to France at: " + frDateTime); // 2021-05-01T20:06+02:00[Europe/Paris]
Output:
Depart from Vietnam at: 2021-05-01T12:00+07:00[Asia/Ho_Chi_Minh]
Arrive to France at: 2021-05-01T20:06+02:00[Europe/Paris]
Compte tenu de l'exemple ci-dessus, vous arriverez en France à 20h06 le 1er mai 2021 DST.

4. ZonedDateTime methods

La classe ZonedLocalDate ne fournit aucun constructeur pour créer l'objet. Vous pouvez utiliser plutôt l'une des méthodes de fabrique statiques suivantes :
public static ZonedDateTime now()  

public static ZonedDateTime now(ZoneId zone)  

public static ZonedDateTime now(Clock clock)  

public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone)  

public static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone)

public static ZonedDateTime of(int year, int month, int dayOfMonth,
                               int hour, int minute, int second,
                               int nanoOfSecond, ZoneId zone)

public static ZonedDateTime ofLocal(LocalDateTime localDateTime,
                               ZoneId zone, ZoneOffset preferredOffset)  

public static ZonedDateTime ofInstant(Instant instant, ZoneId zone)

public static ZonedDateTime ofInstant(LocalDateTime localDateTime,
                               ZoneOffset offset, ZoneId zone)  

public static ZonedDateTime ofStrict(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone)  

public static ZonedDateTime from(TemporalAccessor temporal)  

public static ZonedDateTime parse(CharSequence text)  

public static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter)
La plupart des méthodes de la classe ZonedDateTime sont similaires aux méthodes de la classe LocalDateTime, comme la liste des méthodes ci-dessous. Vous pouvez consulter l'article sur LocalDateTime pour avoir plus d'exemples :
// ----------------------------------------------------
// getX(..) methods
// ----------------------------------------------------

public int getYear()  
public int getMonthValue()
public Month getMonth()
public int getDayOfMonth()  
public int getDayOfYear()  
public DayOfWeek getDayOfWeek()  
public int getHour()  
public int getMinute()  
public int getSecond()  
public int getNano()  
// Inherited from TemporalAccessor interface
public int get(TemporalField field)  
// Inherited from TemporalAccessor interface
public long getLong(TemporalField field)  

// ----------------------------------------------------
// withX(..) methods
// ----------------------------------------------------

public ZonedDateTime withYear(int year)  
public ZonedDateTime withMonth(int month)
public ZonedDateTime withDayOfMonth(int dayOfMonth)  
public ZonedDateTime withDayOfYear(int dayOfYear)  
public ZonedDateTime withHour(int hour)  
public ZonedDateTime withMinute(int minute)
public ZonedDateTime withSecond(int second)  
public ZonedDateTime withNano(int nanoOfSecond)
// Inherited from TemporalAccessor interface
public ZonedDateTime with(TemporalAdjuster adjuster)
// Inherited from Temporal interface
public ZonedDateTime with(TemporalField field, long newValue)  
// ----------------------------------------------------
// plusX(..) methods
// ----------------------------------------------------

public ZonedDateTime plusYears(long years)
public ZonedDateTime plusMonths(long months)
public ZonedDateTime plusWeeks(long weeks)  
public ZonedDateTime plusDays(long days)  
public ZonedDateTime plusHours(long hours)  
public ZonedDateTime plusMinutes(long minutes)
public ZonedDateTime plusSeconds(long seconds)  
public ZonedDateTime plusNanos(long nanos)  
// Inherited from Temporal interface
public ZonedDateTime plus(TemporalAmount amountToAdd)
// Inherited from TemporalAccessor interface
public ZonedDateTime plus(long amountToAdd, TemporalUnit unit)

// ----------------------------------------------------
// minusX(..) methods
// ----------------------------------------------------

public ZonedDateTime minusYears(long years)  
public ZonedDateTime minusMonths(long months)  
public ZonedDateTime minusWeeks(long weeks)
public ZonedDateTime minusDays(long days)  
public ZonedDateTime minusHours(long hours)
public ZonedDateTime minusMinutes(long minutes)  
public ZonedDateTime minusSeconds(long seconds)  
public ZonedDateTime minusNanos(long nanos)  
// Inherited from TemporalAccessor interface
public ZonedDateTime minus(TemporalAmount amountToSubtract)
// Inherited from TemporalAccessor interface
public ZonedDateTime minus(long amountToSubtract, TemporalUnit unit)  

// ----------------------------------------------------
// isSupported(..) methods
// ----------------------------------------------------

// Inherited from TemporalAccessor interface
public boolean isSupported(TemporalField field)

// Inherited from Tempral interface
public boolean isSupported(TemporalUnit unit)  

// ----------------------------------------------------
// ----------------------------------------------------

// Inherited from TemporalAccessor interface
public ValueRange range(TemporalField field)  

// Inherited from TemporalAccessor interface
public <R> R query(TemporalQuery<R> query)  

// Inherited from Temporal interface
public long until(Temporal endExclusive, TemporalUnit unit)  

// Inherited from ChronoZonedDateTime<LocalDate> interface
public String format(DateTimeFormatter formatter)  

public ZonedDateTime truncatedTo(TemporalUnit unit)
Les autres méthodes :
// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZoneId getZone()

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZoneOffset getOffset()  

// Owner
public OffsetDateTime toOffsetDateTime()

// Inherited from ChronoZonedDateTime<LocalDate> interface
public LocalDateTime toLocalDateTime()  

// Inherited from ChronoZonedDateTime<LocalDate> interface
public LocalDate toLocalDate()  

// Inherited from ChronoZonedDateTime<LocalDate> interface
public LocalTime toLocalTime()  

// Owner
public ZonedDateTime withFixedOffsetZone()  

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withEarlierOffsetAtOverlap()  

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withLaterOffsetAtOverlap()

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withZoneSameLocal(ZoneId zone)

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withZoneSameInstant(ZoneId zone)

5. withZoneSameInstant(ZoneId)

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withZoneSameInstant(ZoneId zone)
Renvoyer une copie de cette ZonedDateTime avec le nouveau fuseau horaire et conserver l'instant sur la chronologie. Par exemple, quand il est 12 heures au Vietnam, il est 14 heures au Japon.
ZonedDateTime_withZoneSameInstant_ex1.java
package org.o7planning.zoneddatetime.ex;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class ZonedDateTime_withZoneSameInstant_ex1 {

    public static void main(String[] args) {
        // 2020-01-01 12:00:00
        LocalDateTime localDateTime = LocalDateTime.of(2020, Month.JANUARY, 1, 12, 0, 0);
        
        // Ho Chi Minh City Vietnam. UTC+7
        ZonedDateTime vnDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Asia/Ho_Chi_Minh"));
        System.out.println("VN Datetime: " + vnDateTime); // 2020-01-01T12:00+07:00[Asia/Ho_Chi_Minh]
        
        // Tokyo Japan. UTC+9
        ZonedDateTime  jpDateTime = vnDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
        
        System.out.println("JP Datetime: " + jpDateTime); // 2020-01-01T14:00+09:00[Asia/Tokyo]
    }
}
Output:
VN Datetime: 2020-01-01T12:00+07:00[Asia/Ho_Chi_Minh]
JP Datetime: 2020-01-01T14:00+09:00[Asia/Tokyo]

6. withZoneSameLocal(ZoneId)

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withZoneSameLocal(ZoneId zoneId)
Renvoyer une copie de cette ZonedDateTime avec le nouveau fuseau horaire et conserver les informations de date et heure locales si possible.
Par exemple :
ZonedDateTime_withZoneSameLocal_ex1.java
package org.o7planning.zoneddatetime.ex;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class ZonedDateTime_withZoneSameLocal_ex1 {

    public static void main(String[] args) {
        // 2020-01-01 00:00:00
        LocalDateTime localDateTime = LocalDateTime.of(2020, Month.JANUARY, 1, 0, 0, 0);
        
        // Ho Chi Minh City Vietnam.
        ZonedDateTime vnDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Asia/Ho_Chi_Minh"));
        System.out.println("VN Datetime: " + vnDateTime);
        
        // Chicago US:
        // Same Local Date Time as VN:
        ZonedDateTime chicagoDt = vnDateTime.withZoneSameLocal(ZoneId.of("America/Chicago"));
        
        System.out.println("Chicago Datetime: " + chicagoDt);
    }
}

7. withEarlierOffsetAtOverlap()

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withEarlierOffsetAtOverlap()

United States

European Union
Year
DST Begins at 2 a.m.
DST Ends at 2 a.m.
Summertime period begins at 1 a.m. UT
Summertime period ends at 1 a.m. UT
2017
March 12
November 5
March 26
October 29
2018
March 11
November 4
March 25
October 28
2019
March 10
November 3
March 31
October 27
2020
March 8
November 1
March 29
October 25
2021
March 14
November 7
March 28
October 31
2022
March 13
November 6
March 27
October 30
2023
March 12
November 5
March 26
October 29
2024
March 10
November 3
March 31
October 27
Dans l'exemple ci-dessous sur la méthode withEarlierOffsetAtOverlap(), on considère le centre des États-Unis le 7 novembre 2021. Dans le système d'heure standard, la période d'une heure après la fin de l'heure d'été DST est la période de chevauchement (overlap) entre deux systèmes.
ZonedDateTime_withEarlierOffsetAtOverlap_ex1.java
package org.o7planning.zoneddatetime.ex;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class ZonedDateTime_withEarlierOffsetAtOverlap_ex1 {

    public static void main(String[] args) {
        // Default Offset: -6. When DST ON --> Offset: -5
        ZoneId usCenterZoneId = ZoneId.of("US/Central");
        
        // (Standard Time/offset -6) 2021-11-07  Overlap time: [01:00 --> 2:00)
        LocalDateTime localDateTime = LocalDateTime.of(2021, Month.NOVEMBER, 7, 1, 30, 0);  
        
        // Create a ZonedDateTime object with Fixed Offset = -6.   
        ZonedDateTime zonedDateTime = ZonedDateTime.ofLocal(localDateTime, usCenterZoneId, ZoneOffset.ofHours(-6));
        
        System.out.println("zonedDateTime: " + zonedDateTime);

        // apply withEarlierOffsetAtOverlap()
        ZonedDateTime zonedDateTime2 = zonedDateTime.withEarlierOffsetAtOverlap();
        
        System.out.println("zonedDateTime.withEarlierOffsetAtOverlap(): " + zonedDateTime2);
    }  
}
Output:
zonedDateTime: 2021-11-07T01:30-06:00[US/Central]
zonedDateTime.withEarlierOffsetAtOverlap(): 2021-11-07T01:30-05:00[US/Central]

8. withLaterOffsetAtOverlap()

// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withLaterOffsetAtOverlap()
Dans l'exemple ci-dessous sur la méthode withLaterOffsetAtOverlap(), on considère le centre des États-Unis le 7 novembre 2021. Dans le système DST, la période d'une heure avant la fin de l'heure d'été DST est la période de chevauchement (overlap) entre deux systèmes.
ZonedDateTime_withLaterOffsetAtOverlap_ex1.java
package org.o7planning.zoneddatetime.ex;

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class ZonedDateTime_withLaterOffsetAtOverlap_ex1 {

    public static void main(String[] args) {
        // Default Offset: -6. When DST ON --> Offset: -5
        ZoneId usCenterZoneId = ZoneId.of("US/Central");  
        
        // 2021-11-07 Overlap time: [01:00 --> 2:00)
        LocalDateTime localDateTime = LocalDateTime.of(2021, Month.NOVEMBER, 7, 1, 30, 0);
        
        // Create a ZonedDateTime object.
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, usCenterZoneId);
        
        System.out.println("zonedDateTime: " + zonedDateTime);

        // apply withLaterOffsetAtOverlap()
        ZonedDateTime zonedDateTime2 = zonedDateTime.withLaterOffsetAtOverlap();
        
        System.out.println("zonedDateTime.withLaterOffsetAtOverlap(): " + zonedDateTime2);
    }  
}
Output:
zonedDateTime: 2021-11-07T01:30-05:00[US/Central]
zonedDateTime.withLaterOffsetAtOverlap(): 2021-11-07T01:30-06:00[US/Central]

9. withFixedOffsetZone()

Comme vous le savez, l'objet ZonedDateTime est une combinaison de 3 objets LocalDateTime, ZoneId et ZoneOffset :
ZonedDateTime
public final class ZonedDateTime
        implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {

    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
    private final ZoneId zone;
}
La méthode withFixedOffsetZone() renvoie une copie de cette ZonedDateTime avec son objet ZoneId remplacé par son objet ZoneOffset.
public ZonedDateTime withFixedOffsetZone()
(*) La classe ZoneOffset est une sous-classe de la classe ZoneId.
Cela équivaut à :
ZonedDateTime origin = ...;

ZonedDateTime copy1 = origin.withFixedOffsetZone();

// Same as:

ZonedDateTime copy2 = ZonedDateTime.of(origin.toLocalDateTime(), origin.getOffset());
Par exemple :
ZonedDateTime_withFixedOffsetZone_ex1.java
package org.o7planning.zoneddatetime.ex;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class ZonedDateTime_withFixedOffsetZone_ex1 {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.of(2021, 11, 7, 1, 30, 00);
        ZoneId zoneId = ZoneId.of("US/Central");
        
        ZonedDateTime origin = ZonedDateTime.ofLocal(localDateTime, zoneId, ZoneOffset.ofHours(-6));

        System.out.println("origin: " + origin);
        System.out.println("origin.getZone(): " + origin.getZone());
        System.out.println("origin.getOffset(): " + origin.getOffset());

        System.out.println(" ------------- ");

        // apply withFixedOffsetZone()
        ZonedDateTime copied = origin.withFixedOffsetZone();

        System.out.println("copied: " + copied);
        System.out.println("copied.getZone(): " + copied.getZone());
        System.out.println("copied.getOffset(): " + copied.getOffset());
    }
}
Output:
origin: 2021-11-07T01:30-06:00[US/Central]
origin.getZone(): US/Central
origin.getOffset(): -06:00
 -------------
copied: 2021-11-07T01:30-06:00
copied.getZone(): -06:00
copied.getOffset(): -06:00
Par exemple :
ZonedDateTime_withFixedOffsetZone_ex2.java
package org.o7planning.zoneddatetime.ex;

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

public class ZonedDateTime_withFixedOffsetZone_ex2 {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.of(2021, 11, 7, 1, 30, 00);
        ZoneId zoneId = ZoneId.of("Asia/Ho_Chi_Minh");

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

        System.out.println("origin: " + origin);
        System.out.println("origin.getZone(): " + origin.getZone());
        System.out.println("origin.getOffset(): " + origin.getOffset());

        System.out.println(" ------------- ");

        // apply withFixedOffsetZone()
        ZonedDateTime copied = origin.withFixedOffsetZone();

        System.out.println("copied: " + copied);
        System.out.println("copied.getZone(): " + copied.getZone());
        System.out.println("copied.getOffset(): " + copied.getOffset());
    }
}
Output:
origin: 2021-11-07T01:30+07:00[Asia/Ho_Chi_Minh]
origin.getZone(): Asia/Ho_Chi_Minh
origin.getOffset(): +07:00
 -------------
copied: 2021-11-07T01:30+07:00
copied.getZone(): +07:00
copied.getOffset(): +07:00