o7planning

Java ZonedDateTime Tutorial with Examples

  1. ZonedDateTime
  2. ZonedDateTime supports historical data
  3. ZonedDateTime & DST
  4. ZonedDateTime methods
  5. withZoneSameInstant(ZoneId)
  6. withZoneSameLocal(ZoneId)
  7. withEarlierOffsetAtOverlap()
  8. withLaterOffsetAtOverlap()
  9. withFixedOffsetZone()

1. ZonedDateTime

ZonedDateTime is a class representing date and time with time zone information, located in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.
The ZonedDateTime class is in the java.time package. Like all classes provided by the Java Date Time API, ZonedDateTime is immutable, which means all calculations on ZonedDateTime create a new ZonedDateTime object, so it's safe to be used in multithreading environment.
Before continuing with this article you should learn about GMT, UTC and UT concepts:
  • GMT vs UTC
public final class ZonedDateTime
        implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {

    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
    private final ZoneId zone;
}
Looking at the source code of the ZonedDateTime class, we see that it manages 3 internal objects, in which:
  • The LocalDateTime object contains date and time information.
  • The ZoneId object is the identifier name of the time zone, such as Europe/Paris.
  • The ZoneOffset object contains time-zone offset information, such as +01:30.
Example: With a LocalDateTime object containing only date and time information, we add time zone information to create a ZonedDateTime object containing date, time, and time zone information.
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]
For example: What time is New Year's Eve 2020 in Vietnam equivalent to in Japan and France? The following example will show you such a time conversion:
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]
Example: At 12 o'clock on January 1st, 2020, you fly from Vietnam to Japan. The flight duration is 6 hours 15 minutes. The question is what time will you arrive in Japan?
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 supports historical data

The time zone of a geographic area may vary slightly due to country purposes and geographic location. The great thing is that ZonedDateTime stores those historical data. For example, from 1960 to before June 13, 1975, southern Vietnam used UTC+8 time zone, then switched to UTC+7 time zone to unify with northern Vietnam.
For better understanding, see the example below:
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

Currently, most states in the United States apply Daylight Saving Time (DST). Specifically, from 2 o'clock on the second Sunday of March to 2 o'clock on the first Sunday in November, the clocks will be set 1 hour earlier.

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
In 2021 in the US, DST starts at 2:00 a.m. on March 14th and ends at 2:00 a.m. on November 7th. Let's see how the Java 8 Date Time API resolves DST.
We will create a ZonedDateTime object representing 1:30 a.m. on March 14th, 2021 in the central US. Then add 1 hour to it and see what happens.
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:
Example: Suppose at 12 o'clock on May 1st, 2021 you fly from Vietnam to France, the flight duration is 13 hours and 6 minutes. So what time will you arrive in France?
Note: In 2021, DST in France starts at 1 a.m. on March 28th and ends at 1 a.m. on October 31st. France's default time zone is UTC+1, during DST it uses UTC+2 time zone.
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]
The example above shows that you will arrive in France at 20:06 on May 1st, 2021 DST.

4. ZonedDateTime methods

The ZonedLocalDate class does not provide any constructor to create the object. Instead, you can use one of the following static factory methods:
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)
Most of the methods of the ZonedDateTime class are similar to the methods of the LocalDateTime class, such as the list of methods below. You can check out the article about LocalDateTime to have more examples:
// ----------------------------------------------------
// 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)
Other methods:
// 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)
Return a copy of this ZonedDateTime with the new time zone and keep the instant on the timeline. For example, 12 o'clock in Vietnam will be changed to 14 o'clock in the Japanese time zone.
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)
Return a copy of this ZonedDateTime with the new time zone and retain the local date time information if possible.
Example:
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
In the below example of the withEarlierOffsetAtOverlap() method, we consider the central US November 7th, 2021. In the standard time system, the 1 hour period after DST ends is the overlapping period between two systems.
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()
In the below example of the withLaterOffsetAtOverlap() method, we consider the central US November 7, 2021. In the DST system, the 1 hour period before DST ends is the overlapping period between two systems.
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()

As you know, the ZonedDateTime object is a combination of 3 LocalDateTime, ZoneId and ZoneOffset objects:
ZonedDateTime
public final class ZonedDateTime
        implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {

    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
    private final ZoneId zone;
}
The withFixedOffsetZone() method returns a copy of this ZonedDateTime with its ZoneId object replaced by its ZoneOffset object.
public ZonedDateTime withFixedOffsetZone()
(*) The ZoneOffset class is a subclass of the ZoneId class.
This is equivalent to:
ZonedDateTime origin = ...;

ZonedDateTime copy1 = origin.withFixedOffsetZone();

// Same as:

ZonedDateTime copy2 = ZonedDateTime.of(origin.toLocalDateTime(), origin.getOffset());
Example:
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
Example:
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