betacode

Руководство Java ZonedDateTime

  1. ZonedDateTime
  2. ZonedDateTime поддерживает исторические данные
  3. ZonedDateTime & DST
  4. ZonedDateTime methods
  5. withZoneSameInstant(ZoneId)
  6. withZoneSameLocal(ZoneId)
  7. withEarlierOffsetAtOverlap()
  8. withLaterOffsetAtOverlap()
  9. withFixedOffsetZone()

1. ZonedDateTime

ZonedDateTime - это класс, представляющий дату и время с информацией о часовом поясе, который находится в календарной системе ISO-8601, такой как 2007-12-03T10:15:30+01:00 Europe/Paris.
Класс ZonedDateTime находится в пакете java.time. Как и все классы, предоставляемые Java Date Time API, ZonedDateTime является неизменяемым (immutable), это означает, что все вычисления в ZonedDateTime создают новый объект ZonedDateTime, поэтому его безопасно использовать в среде multithreading.
Прежде чем продолжить эту статью, вам следует ознакомиться с понятиями GMT, UTC и 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;
}
Глядя на исходный код класса ZonedDateTime, мы видим, что он управляет 3 внутренними объектами, в которых:
  • Объект LocalDateTime содержит информацию о дате и времени.
  • Объект ZoneId - это имя идентификатора часового пояса, например, Europe/Paris.
  • Объект ZoneOffset содержит информацию о смещении часового пояса, например +01:30.
Например: С помощью объекта LocalDateTime, содержащего только информацию о дате и времени, мы добавляем информацию о часовом поясе, чтобы создать объект ZonedDateTime, содержащий информацию о дате, времени и часовом поясе.
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]
Например: Какое время в канун Нового 2020 года во Вьетнаме эквивалентно времени в Японии и Франции? Следующий пример покажет вам такое преобразование времени:
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]
Например: В 12 часов 1 января 2020 года вы вылетаете из Вьетнама в Японию, длительность полета составляет 6 часов 15 минут. Вопрос в том, во сколько вы приедете в Японию?
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 поддерживает исторические данные

Часовой пояс географического района может незначительно отличаться в зависимости от целей страны и географического положения. Самое замечательное, что ZonedDateTime хранит эти исторические данные. Например, с 1960 года по 13 июня 1975 года южный Вьетнам использовал часовой пояс UTC+8, затем переключился на часовой пояс UTC+7, чтобы объединиться с северным Вьетнамом.
Для лучшего понимания см. пример ниже:
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

В настоящее время в большинстве штатов Соединенных Штатов применяется летнее время (Daylight Saving Time - DST). В частности, с 2 часов второго воскресенья марта до 2 часов первого воскресенья ноября часы будут установлены на 1 час раньше.

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
В 2021 году в США летнее время начинается в 2:00 14 марта и заканчивается в 2:00 7 ноября. Давайте посмотрим, как Java 8 Date Time API разрешает DST.
Мы создадим объект ZonedDateTime, представляющий 1:30 утра 14 марта 2021 года в центральной части США. Затем добавьте к этому 1 час и посмотрите, что произойдет.
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:
Например: Предположим, в 12 часов 1 мая 2021 года вы летите из Вьетнама во Францию, продолжительность полета составляет 13 часов 6 минут. Итак, во сколько вы приедете во Францию?
Примечание: В 2021 году DST во Франции начинается в 1 час ночи 28 марта и заканчивается в 1 час ночи 31 октября. Часовой пояс Франции по умолчанию - UTC+1, во время DST используется часовой пояс 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]
Приведенный выше пример показывает, что вы приедете во Францию в 20:06 1 мая 2021 года по времени DST.

4. ZonedDateTime methods

Класс ZonedLocalDate не предоставляет никакого конструктора для создания объекта. Вместо этого вы можете использовать один из следующих статических заводских методов:
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)
Большинство методов класса ZonedDateTime аналогичны методам класса LocalDateTime, таким как приведенный ниже список методов. Вы можете ознакомиться со статьей о LocalDateTime, чтобы получить больше примеров:
  • Руководство Java LocalDateTime
// ----------------------------------------------------
// 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)
Другие методы:
// 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)
Возвращайте копию этого ZonedDateTime с новым часовым поясом и сохраните момент (instant) на временной шкале. Например, 12 часов во Вьетнаме будут изменены на 14 часов в японском часовом поясе.
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)
Возвращайте копию этого ZonedDateTime с новым часовым поясом и, по возможности, сохраните информацию о местной дате и времени.
Например:
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
В приведенном ниже примере о методе withEarlierOffsetAtOverlap() мы рассмотрим центральную часть США 7 ноября 2021 года. В стандартной системе времени период в 1 час после окончания DST является периодом перекрытия (overlap) между двумя системами.
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()

No ADS
// Inherited from ChronoZonedDateTime<LocalDate> interface
public ZonedDateTime withLaterOffsetAtOverlap()
В приведенном ниже примере о методе withLaterOffsetAtOverlap() мы рассмотрим центральный США 7 ноября 2021 года. В системе DST период за 1 час до окончания DST является периодом перекрытия (overlap) между двумя системами.
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()

No ADS
Как вы знаете, объект ZonedDateTime представляет собой комбинацию из 3 объектов LocalDateTime, ZoneId и ZoneOffset:
ZonedDateTime
public final class ZonedDateTime
        implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {

    private final LocalDateTime dateTime;
    private final ZoneOffset offset;
    private final ZoneId zone;
}
Метод withFixedOffsetZone() возвращает копию этого ZonedDateTime с объектом ZoneId, замененным объектом ZoneOffset.
public ZonedDateTime withFixedOffsetZone()
(*) Класс ZoneOffset является подклассом класса ZoneId.
Это эквивалентно:
ZonedDateTime origin = ...;

ZonedDateTime copy1 = origin.withFixedOffsetZone();

// Same as:

ZonedDateTime copy2 = ZonedDateTime.of(origin.toLocalDateTime(), origin.getOffset());
Например:
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
Например:
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
No ADS