深入Java8-日期时间API:ZonedDateTime类

zoneId、ZoneOffset、Date、LocalDateTime、ZonedDateTime、OffsetDateTime的区别 1、zoneId2、ZoneOffset继承了zoneId3、ZoneOffset 和 TimeZone区别ZoneOffset 和 TimeZone 是 Java 编程语言中处理时区信息的两个不同的类。ZoneOffset 类:ZoneOffset 是 Java 8 中引入的日期时间 API 的一部分,位于 java.time 包中。它代表了与协调世界时(UTC)之间的固定时间偏移,以固定的小时和分钟表示。例如,+02:00 表示时间比协调世界时快 2 小时。 阅读详情

JDK版本:11

关于ZonedDateTime

ZonedDateTime是Java 8中引入的一个不可变且线程安全的数据类型,用于表示带有时区的日期和时间。与LocalDateTime相比,ZonedDateTime可以存储时区信息,并能够处理模糊的本地日期时间。

ZonedDateTime可以表示从本地时间线LocalDateTime到即时时间线Instant之间的日期和时间。两个时间线之间的差异是UTC /格林威治的偏移量,由ZoneOffset表示。在两个时间线之间转换涉及使用从ZoneId访问的ZoneId计算偏移量。

ZonedDateTime的常用方法包括获取年份、月份、日期、小时、分钟、秒等信息的get方法,以及计算两个日期之间的差值的minus方法等。ZonedDateTime还提供了用于获取当前日期和时间的now方法,以及用于将ZonedDateTime转换为其它日期/时间类型的toLocalDate、toLocalTime等方法。

需要注意的是,ZonedDateTime在进行时区转换时可能会遇到夏令时调整的情况,此时需要使用正确的时区信息以避免错误的出现。另外,在处理涉及时区的日期和时间时,需要考虑时区偏移量以及时间线之间的差异等问题。

核心方法

ZonedDateTime#now()

ZonedDateTime#now() 用于获取当前时间。它返回一个表示当前日期和时间的ZonedDateTime 对象,包括时区和偏移量。

@Test
public void test() {
    ZonedDateTime zonedDateTime = ZonedDateTime.now();
    System.out.println(zonedDateTime);//输出结果:2023-11-29T13:31:38.124890400+08:00[Asia/Shanghai]
}

ZonedDateTime#of(...)、ZonedDateTime#ofLocal(...)、ZonedDateTime#ofInstant(...)、ZonedDateTime#ofStrict(...)

  • ZonedDateTime#of(...): 该方法用于从年、月、日、时、分、秒和时区中获取ZonedDateTime的实例。所有这些值分别是年、月、日、时、分、秒和时区作为参数传递。
  • ZonedDateTime#ofLocal(LocalDateTime, ZoneId, ZoneOffset): 该方法用于使用ZonmeId和首选偏移量从本地日期时间创建ZonedDateTime实例。
  • ZonedDateTime#ofInstant(Instant, ZoneId): 该方法用于从Instant和ZoneId中获取ZonedDateTime实例。
  • ZonedDateTime#ofStrict(LocalDateTime, ZoneId, ZoneOffset): 该方法用于从严格模式下的本地日期时间创建ZonedDateTime实例。
@Test
public void test2() {
    ZoneId zoneId = ZoneId.systemDefault();
    System.out.println(zoneId.getId());//输出结果:Asia/Shanghai
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    System.out.println(zonedDateTime);//输出结果:2023-11-29T13:32:12+08:00[Asia/Shanghai]
    LocalDate localDate = LocalDate.of(2023, 11, 29);
    LocalTime localTime = LocalTime.of(13, 32, 12, 0);
    ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDate, localTime, zoneId);
    System.out.println(zonedDateTime1);//输出结果:2023-11-29T13:32:12+08:00[Asia/Shanghai]
}

ZonedDateTime#from(...)

ZonedDateTime#from() 用于从其他时间单位(如 LocalDateTime, LocalDate, LocalTime, Instant 等)创建 ZonedDateTime 对象。这个方法接收一个 TemporalAccessor 对象,然后根据该对象的时间单位,将其转换为 ZonedDateTime 对象。例如,如果我们有一个 OffsetDateTime 对象,我们可以使用 ZonedDateTime#from() 方法将其转换为 ZonedDateTime 对象

@Test
public void test3() {
    OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneOffset.ofHours(-5));
    ZonedDateTime from = ZonedDateTime.from(offsetDateTime);
    System.out.println(from);//输出结果:2023-11-29T13:32:12-05:00
}

ZonedDateTime#parse(...)

ZonedDateTime#parse() 用于将字符串解析为 ZonedDateTime 对象。这个方法接受一个字符串参数,并尝试将其解析为 

ZonedDateTime 格式。这里要特别注意:如果字符格式不符合规范,则会抛出异常;

@Test
public void test4() {
    String str = "2023-11-29T13:32:12+08:00[Asia/Shanghai]";
    ZonedDateTime zonedDateTime = ZonedDateTime.parse(str);
    System.out.println(zonedDateTime);//输出结果:2023-11-29T13:32:12+08:00[Asia/Shanghai]
}

ZonedDateTime#isSupported(...)

ZonedDateTime#isSupported(...) 用于确定当前时间是否支持给定的时间字段。这个方法接受一个 TemporalField 对象作为参数,如果当前时间支持该字段,则返回 true,否则返回 false。

@Test
public void test5() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    boolean supported = zonedDateTime.isSupported(ChronoUnit.YEARS);
    boolean supported2 = zonedDateTime.isSupported(ChronoField.YEAR);
    System.out.println(supported);//输出结果:true
    System.out.println(supported2);//输出结果:true
}

ZonedDateTime#range(...)

ZonedDateTime#range(...) 是 用于获取给定时间字段的范围。这个方法接受一个 TemporalField 对象作为参数,返回一个 TemporalRange 对象,表示该字段的范围。

@Test
public void test6() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ValueRange range = zonedDateTime.range(ChronoField.DAY_OF_MONTH);
    long minimum = range.getMinimum();
    long maximum = range.getMaximum();
    System.out.println(minimum);//输出结果:true
    System.out.println(maximum);//输出结果:true
}

ZonedDateTime#get(...)、ZonedDateTime#getLong(...)、ZonedDateTime#getOffset(...)

  • ZonedDateTime#get(...):该方法用于从ZonedDateTime对象获取指定字段的值。例如,调用get()方法并传入一个表示“小时”的字段,将返回当前时间的小时值。如果查询的字段值超出该字段的有效范围,或者不支持该字段,可能会引发异常。
  • ZonedDateTime#getLong(...):这个方法用于获取ZonedDateTime对象中指定字段的长整型值。同样,如果查询的字段值超出有效范围,或者不支持该字段,可能会引发异常。
  • ZonedDateTime#getOffset(...):此方法用于获取ZonedDateTime对象的时区偏移量。它返回一个表示偏移量的ZoneOffset对象。

这些方法都可用于处理和操作具有时区信息的时间,但get()和getLong()方法更侧重于获取时间的特定部分,而getOffset()则关注于获取时区的偏移量。

@Test
public void test7() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    int year = zonedDateTime.get(ChronoField.YEAR);
    long yearOfYear = zonedDateTime.getLong(ChronoField.YEAR);
    int month = zonedDateTime.get(ChronoField.MONTH_OF_YEAR);
    int day = zonedDateTime.get(ChronoField.DAY_OF_MONTH);
    int dayOfYear = zonedDateTime.get(ChronoField.DAY_OF_YEAR);
    ZoneOffset offset = zonedDateTime.getOffset();
    System.out.println(year);//输出结果:2023
    System.out.println(yearOfYear);//输出结果:2023
    System.out.println(month);//输出结果:11
    System.out.println(day);//输出结果:29
    System.out.println(dayOfYear);//输出结果:333
    System.out.println(offset);//输出结果:+08:00
}

ZonedDateTime#getZone(...)

ZonedDateTime#getZone() 用于获取该对象的时区。此方法返回一个 ZoneId 对象,表示 ZonedDateTime 对象的时区。ZoneId 是 Java 8 中表示时区的类。

    @Test
    public void test8() {
        ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("America/New_York"));
        String zoneId = zonedDateTime.getZone().getId();
        System.out.println(zoneId);//输出结果:America/New_York
    }

ZonedDateTime#withZoneSameLocal(...)、ZonedDateTime#withZoneSameInstant(...)、ZonedDateTime#withFixedOffsetZone(...)

  • ZonedDateTime#withZoneSameLocal():用于通过更改时区来返回此ZonedDateTime对象的副本,如果可能的话不更改本地日期时间。仅当本地日期时间对于新区域无效时才更改本地日期时间。此方法尽量保持相同的本地时间,同时改变时区。
  • 使用场景:当你需要确保在特定时区下的本地时间不变,而仅仅需要改变日期的表示时区时,可以使用此方法。
  • ZonedDateTime#withZoneSameInstant():这个方法通过更改时区且不带瞬时值来返回此ZonedDateTime对象的副本。换句话说,它将尝试保持相同的时间戳,但可能在不同的时区下。当你需要确保在特定时区下的时间戳不变,而仅仅需要改变日期的表示时区时,可以使用此方法。
  • ZonedDateTime#withFixedOffsetZone():这个方法允许你使用固定的偏移量来创建新的ZonedDateTime对象。偏移量表示从UTC(协调世界时间)到当前时区的偏移量。当你需要创建一个具有特定偏移量的ZonedDateTime对象,而不管具体的时区是什么时,可以使用此方法。
@Test
public void test9() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime1 = zonedDateTime.withZoneSameLocal(ZoneId.of(("America/New_York")));
    System.out.println(zonedDateTime1);//输出结果:2023-11-29T13:32:12-05:00[America/New_York]
    ZonedDateTime zonedDateTime2 = zonedDateTime.withZoneSameInstant(ZoneId.of(("America/New_York")));
    System.out.println(zonedDateTime2);//输出结果:2023-11-29T00:32:12-05:00[America/New_York]
    ZonedDateTime zonedDateTime3 = zonedDateTime.withFixedOffsetZone();
    System.out.println(zonedDateTime3);//输出结果:2023-11-29T13:32:12+08:00
}

ZonedDateTime#toLocalDateTime(...)、ZonedDateTime#toLocalDate(...)、ZonedDateTime#toLocalTime(...)

ZonedDateTime类的toLocalDateTime()方法、toLocalDate()方法和toLocalTime()方法分别用于返回该日期时间对象的LocalDateTime部分、LocalDate部分和LocalTime部分。以下是每个方法的功能作用和使用场景:

  • ZonedDateTime#toLocalDateTime():该方法返回一个与当前ZonedDateTime对象日期和时间部分相同的LocalDateTime对象。它主要用于需要同时获取日期和时间但不需要时区和偏移量信息的情况。例如,在记录事件发生的时间、计算时间间隔或进行日期时间运算时,可以使用该方法。
  • ZonedDateTime#toLocalDate():该方法返回一个与当前ZonedDateTime对象日期部分相同的LocalDate对象。它主要用于需要获取日期但不需要具体时间信息的情况。例如,在记录一个事件发生的日期、计算日期间隔或进行日期运算时,可以使用该方法。
  • ZonedDateTime#toLocalTime():该方法返回一个与当前ZonedDateTime对象时间部分相同的LocalTime对象。它主要用于需要获取时间但不需要具体日期信息的情况。例如,在记录一个事件发生的时间、计算时间间隔或进行时间运算时,可以使用该方法。

这些方法提供了一种灵活的方式来获取和处理日期和时间的不同组成部分。通过将ZonedDateTime对象转换为LocalDateTime、LocalDate或LocalTime对象,可以更方便地进行各种日期和时间相关的操作。

@Test
public void test10() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
    System.out.println(localDateTime);//输出结果:2023-11-29T13:32:12
    LocalDate localDate = zonedDateTime.toLocalDate();
    System.out.println(localDate);//输出结果:2023-11-29
    LocalTime localTime = zonedDateTime.toLocalTime();
    System.out.println(localTime);//输出结果:13:32:12
}

ZonedDateTime#getYear(...)、ZonedDateTime#getMonthValue(...)、ZonedDateTime#getMonth(...)、ZonedDateTime#getDayOfMonth(...)、ZonedDateTime#getDayOfYear(...)、ZonedDateTime#getDayOfWeek(...)、ZonedDateTime#getHour(...)、ZonedDateTime#getMinute(...)、ZonedDateTime#getSecond(...)、ZonedDateTime#getNano(...)

  • ZonedDateTime#getYear(...):这个方法的功能是获取年份字段。它返回该年份的原始int值。此方法返回的年份是proleptic,即根据UTC/格林威治标准时间相对应的本地日期时间与区域ID规则定义的有效偏移量来获得。
  • ZonedDateTime#getMonthValue(...):这个方法的功能是获取月份字段的值。它返回一个表示月份的整数,范围从1(一月)到12(十二月)。
  • ZonedDateTime#getMonth(...):这个方法的功能是获取月份字段。它返回一个表示月份的枚举值,如JANUARY、FEBRUARY等。
  • ZonedDateTime#getDayOfMonth(...):这个方法的功能是获取一个月中的日期字段。它返回一个表示一个月中某一天的整数,范围从1到该月的最大天数。
  • ZonedDateTime#getDayOfYear(...):这个方法的功能是获取一年中的日期字段。它返回一个表示一年中某一天的整数,范围从1到365(或366在一些年份)。
  • ZonedDateTime#getDayOfWeek(...):这个方法的功能是获取一周中的日期字段。它返回一个表示星期几的枚举值,如SUNDAY、MONDAY等。
  • ZonedDateTime#getHour(...):这个方法的功能是获取小时字段。它返回一个表示小时的整数,范围从0(午夜)到23(晚上11点)。
  • ZonedDateTime#getMinute(...):这个方法的功能是获取分钟字段。它返回一个表示分钟的整数,范围从0到59。
  • ZonedDateTime#getSecond(...):这个方法的功能是获取秒字段。它返回一个表示秒数的整数,范围从0到59。
  • ZonedDateTime#getNano(...):这个方法的功能是获取毫秒字段的一部分(即纳秒)。它返回一个表示纳秒数的整数,范围从0到999999999。

这些方法的作用是根据给定的时间点获取不同的时间单位信息。主要的使用场景:

  • 获取特定时间点的年、月、日、时、分、秒和纳秒等信息。
  • 在日期和时间计算中,使用这些方法来分析和操作日期和时间数据。
  • 在需要精确到纳秒级别的计算或记录中,使用这些方法来获取和操作时间信息。
@Test
public void test11() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    int year = zonedDateTime.getYear();
    int monthValue = zonedDateTime.getMonthValue();
    int dayOfMonth = zonedDateTime.getDayOfMonth();
    int dayOfYear = zonedDateTime.getDayOfYear();
    int hour = zonedDateTime.getHour();
    System.out.println(year);//输出结果:2023
    System.out.println(monthValue);//输出结果:11
    System.out.println(dayOfMonth);//输出结果:29
    System.out.println(dayOfYear);//输出结果:333
    System.out.println(hour);//输出结果:13
}

ZonedDateTime#with(...)、ZonedDateTime#withYear(...)、ZonedDateTime#withMonth(...)、ZonedDateTime#withDayOfMonth(...)、ZonedDateTime#withDayOfYear(...)、ZonedDateTime#withHour(...)、ZonedDateTime#withMinute(...)、ZonedDateTime#withSecond(...)、ZonedDateTime#withNano(...)

  • ZonedDateTime#with(TemporalAdjuster adjuster):该方法允许您使用指定的调整器对象对日期/时间进行调整。这可以用于执行各种日期/时间相关的操作,例如更改日期、时间或时区等。返回的是一个新的ZonedDateTime对象,它是原始对象的副本,不会影响原始对象。
  • ZonedDateTime#withYear(int year):这个方法用于更改ZonedDateTime中的年份。它返回一个新的ZonedDateTime对象,其中包含更改后的年份和原始的月份、日期、小时、分钟、秒和纳秒。此方法在本地时间轴上操作,更改本地日期时间的年份以及此操作之后的本地日期时间使用区域ID获取偏移量,将其转换回ZonedDateTime。当转换回ZonedDateTime时,如果本地日期时间重叠,则将尽可能保留偏移量,否则将使用较早的偏移量。
  • ZonedDateTime#withMonth(int month):这个方法用于更改ZonedDateTime中的月份。它返回一个新的ZonedDateTime对象,其中包含更改后的月份和原始的年份、日期、小时、分钟、秒和纳秒。
  • ZonedDateTime#withDayOfMonth(int dayOfMonth):这个方法用于更改ZonedDateTime中的日期。它返回一个新的ZonedDateTime对象,其中包含更改后的日期和原始的年份、月份、小时、分钟、秒和纳秒。
  • ZonedDateTime#withDayOfYear(int dayOfYear):这个方法用于更改ZonedDateTime中的一年中的日期。它返回一个新的ZonedDateTime对象,其中包含更改后的日期和原始的年份、月份、小时、分钟、秒和纳秒。
  • ZonedDateTime#withHour(int hour):这个方法用于更改ZonedDateTime中的小时。它返回一个新的ZonedDateTime对象,其中包含更改后的小时和原始的年份、月份、日期、分钟、秒和纳秒。
  • ZonedDateTime#withMinute(int minute):这个方法用于更改ZonedDateTime中的分钟。它返回一个新的ZonedDateTime对象,其中包含更改后的分钟和原始的年份、月份、日期、小时、秒和纳秒。
  • ZonedDateTime#withSecond(int second):这个方法用于更改ZonedDateTime中的秒数。它返回一个新的ZonedDateTime对象,其中包含更改后的秒数和原始的年份、月份、日期、小时、分钟和纳秒。
  • ZonedDateTime#withNano(int nano):这个方法用于更改ZonedDateTime中的纳秒数。它返回一个新的ZonedDateTime对象,其中包含更改后的纳秒数和原始的年份、月份、日期、小时、分钟和秒。

这些方法的使用场景包括但不限于以下情况:

  • 在需要对日期/时间进行精细操作或调整时,例如更改年、月、日等字段或执行更复杂的日期/时间计算时,可以使用这些方法。
  • 在需要创建具有特定日期/时间信息的副本或新的日期/时间对象时,可以使用这些方法。
  • 在需要进行时区转换或处理时,可以使用这些方法来获取特定时区下的日期/时间信息。
@Test
public void test12() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime1 = zonedDateTime.with(ChronoField.YEAR, 2022);
    System.out.println(zonedDateTime1);//输出结果2022-11-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime2 = zonedDateTime.withYear(2022);
    System.out.println(zonedDateTime2);//输出结果2022-11-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime3 = zonedDateTime.with(ChronoField.DAY_OF_MONTH, 1);
    System.out.println(zonedDateTime3);//输出结果2023-11-01T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime4 = zonedDateTime.with(ChronoField.HOUR_OF_DAY, 1);
    System.out.println(zonedDateTime4);//输出结果:2023-11-29T01:32:12+08:00[Asia/Shanghai]
}

ZonedDateTime#truncatedTo(...)

ZonedDateTime#truncatedTo(TemporalUnit unit) 的主要作用是将当前的ZonedDateTime对象截断到给定的时间单位,并返回一个新的ZonedDateTime对象。具体来说,这个方法接受一个 TemporalUnit 参数,该参数表示要截断的时间单位。可能的值包括 DAYS、HOURS、MICROSECONDS、MILLISECONDS、MINUTES、NANOSECONDS、SECONDS 等。这个方法将忽略时间单位比指定单位更小的时间单位,例如,如果将日期时间截断到分钟,那么该方法将忽略秒和毫秒字段。

@Test
public void test13() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime1 = zonedDateTime.truncatedTo(ChronoUnit.DAYS);
    System.out.println(zonedDateTime1);//输出结果:2023-11-29T00:00+08:00[Asia/Shanghai]
}

ZonedDateTime#plus(...)、ZonedDateTime#plusYears(...)、ZonedDateTime#plusMonths(...)、ZonedDateTime#plusWeeks(...)、ZonedDateTime#plusDays(...)、ZonedDateTime#plusHours(...)、ZonedDateTime#plusMinutes(...)、ZonedDateTime#plusSeconds(...)、ZonedDateTime#plusNanos(...)

  • ZonedDateTime#plus(...):此方法用于返回此日期时间的副本,其中添加了指定的单位数量。它接受两个参数:amountToAdd(要添加到结果中的单位数量,可能为负)和unit(要添加数量的单位)。返回值是根据此日期时间返回的ZonedDateTime,并添加了指定的数量。该数量通常为Period或Duration,但可以是实现TemporalAmount接口的任何其他类型。当由于不支持该单位或由于其他原因而无法添加数量时,会抛出异常。
  • ZonedDateTime#plusYears(...):此方法用于在此ZonedDateTime中添加年数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusMonths(...):此方法用于在此ZonedDateTime中添加月数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusWeeks(...):此方法用于在此ZonedDateTime中添加周数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusDays(...):此方法用于在此ZonedDateTime中添加天数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusHours(...):此方法用于在此ZonedDateTime中添加小时数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusMinutes(...):此方法用于在此ZonedDateTime中添加分钟数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusSeconds(...):此方法用于在此ZonedDateTime中添加秒数,并在添加后返回ZonedDateTime的副本。
  • ZonedDateTime#plusNanos(...):此方法用于在此ZonedDateTime中添加纳秒数,并在添加后返回ZonedDateTime的副本。
@Test
public void test14() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime1 = zonedDateTime.plus(1, ChronoUnit.YEARS);
    System.out.println(zonedDateTime1);//输出结果:2024-11-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime2 = zonedDateTime.plusYears(1);
    System.out.println(zonedDateTime2);//输出结果:2024-11-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime3 = zonedDateTime.plusMonths(1);
    System.out.println(zonedDateTime3);//输出结果:2023-12-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime4 = zonedDateTime.plusDays(1);
    System.out.println(zonedDateTime4);//输出结果:2023-11-30T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime5 = zonedDateTime.plusMinutes(28);
    System.out.println(zonedDateTime5); //输出结果:2023-11-29T14:00:12+08:00[Asia/Shanghai]
}

ZonedDateTime#minus(...)、ZonedDateTime#minusYears(...)、ZonedDateTime#minusMonths(...)、ZonedDateTime#minusWeeks(...)、ZonedDateTime#minusDays(...)、ZonedDateTime#minusHours(...)、ZonedDateTime#minusMinutes(...)、ZonedDateTime#minusSeconds(...)、ZonedDateTime#minusNanos(...)

  • ZonedDateTime#minus(...):此方法用于返回此日期时间的副本,其中减去指定的单位数量。它接受两个参数:amountToSubtract表示要减去的单位量,可能为负数;unit表示要减去的量的单位。此方法基于本地时间轴进行操作,将本地日期时间减去指定的年、月、日、时、分、秒和纳秒等单位。使用此方法时,需要确保减去的结果在支持的日期范围内,否则可能会抛出异常。
  • ZonedDateTime#minusYears(...):此方法用于从当前日期时间减去指定数量的年份。它接受一个表示年份的参数,该参数可以是负数。此方法在本地时间轴上操作,将从本地日期时间中减去年份,并使用区域ID获取偏移量。当转换回ZonedDateTime时,如果本地日期时间重叠,将尽可能保留偏移量,否则将使用较早的偏移量。此实例是不可变的,不受此方法调用的影响。
  • ZonedDateTime#minusMonths(...):此方法用于从当前日期时间减去指定数量的月份。它接受一个表示月份的参数。此方法在本地时间轴上操作,将从本地日期时间中减去月份。
  • ZonedDateTime#minusWeeks(...):此方法用于从当前日期时间减去指定数量的周数。它接受一个表示周数的参数。此方法在本地时间轴上操作,将从本地日期时间中减去周数。
  • ZonedDateTime#minusDays(...):此方法用于从当前日期时间减去指定数量的天数。它接受一个表示天数的参数。此方法在本地时间轴上操作,将从本地日期时间中减去天数。
  • ZonedDateTime#minusHours(...):此方法用于从当前日期时间减去指定的小时数。它接受一个表示小时数的参数。此方法在本地时间轴上操作,将从本地日期时间中减去小时数。
  • ZonedDateTime#minusMinutes(...):此方法用于从当前日期时间减去指定的分钟数。它接受一个表示分钟数的参数。此方法在本地时间轴上操作,将从本地日期时间中减去分钟数。
  • ZonedDateTime#minusSeconds(...):此方法用于从当前日期时间减去指定的秒数。它接受一个表示秒数的参数。此方法在本地时间轴上操作,将从本地日期时间中减去秒数。
  • ZonedDateTime#minusNanos(...):此方法用于从当前日期时间减去指定的纳秒数。它接受一个表示纳秒数的参数。此方法在本地时间轴上操作,将从本地日期时间中减去纳秒数。
@Test
public void test15() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime1 = zonedDateTime.minus(1, ChronoUnit.YEARS);
    System.out.println(zonedDateTime1);//输出结果:2022-11-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime2 = zonedDateTime.minusYears(1);
    System.out.println(zonedDateTime2);//输出结果:2022-11-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime3 = zonedDateTime.minusMonths(1);
    System.out.println(zonedDateTime3);//输出结果:2023-10-29T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime4 = zonedDateTime.minusDays(1);
    System.out.println(zonedDateTime4);//输出结果:2023-11-28T13:32:12+08:00[Asia/Shanghai]
    ZonedDateTime zonedDateTime5 = zonedDateTime.minusMinutes(28);
    System.out.println(zonedDateTime5); //输出结果:2023-11-29T13:04:12+08:00[Asia/Shanghai]
}

ZonedDateTime#query(...)

ZonedDateTime#query(...) 用于查询与当前 ZonedDateTime 对象相关的信息。该方法接受一个 TemporalQuery 参数,用于指定要查询的信息类型。TemporalQuery 是一个函数式接口,用于从给定的时间对象中提取所需的信息。

@Test
public void test16() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    TemporalQuery<Integer> temporalQuery=item->item.get(ChronoField.DAY_OF_YEAR);
    Integer dayOfYear = zonedDateTime.query(temporalQuery);
    System.out.println(dayOfYear); //输出结果:333
}

ZonedDateTime#until(...)

ZonedDateTime#until(ZonedDateTime) 用于根据单个TemporalUnit计算两个日期时间之间的时间差。

@Test
public void test17() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2022, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime2 = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    long until = zonedDateTime.until(zonedDateTime2, ChronoUnit.MONTHS);
    System.out.println(until); //输出结果:12
}

ZonedDateTime#format(...)

ZonedDateTime#format() 用于将当前对象的时间信息按照指定的格式进行格式化,并返回一个字符串表示。该方法接受一个DateTimeFormatter 参数,用于指定日期时间的格式。

@Test
public void test18() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2022, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    String format = zonedDateTime.format(DateTimeFormatter.ISO_DATE);
    System.out.println(format); //输出结果:2022-11-29+08:00
}

ZonedDateTime#toOffsetDateTime(...)

ZonedDateTime#toOffsetDateTime() 用于将当前对象转换为一个 OffsetDateTime 对象。OffsetDateTime 是 Java 中的一个日期时间类,它表示一个带有时间偏移量的日期时间,通常用于处理具有不同时区的日期时间。

ZonedDateTime 对象表示一个具有时区的日期时间,而 OffsetDateTime 对象则表示一个具有时间偏移量的日期时间。因此,通过调用 toOffsetDateTime() 方法,可以将 ZonedDateTime 对象转换为一个 OffsetDateTime 对象,以便进行进一步的处理或操作。

@Test
public void test19() {
    ZonedDateTime zonedDateTime = ZonedDateTime.of(2022, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
    OffsetDateTime offsetDateTime = zonedDateTime.toOffsetDateTime();
    System.out.println(offsetDateTime); //输出结果:2022-11-29T13:32:12+08:00
}

使用场景

ZonedDateTime常用于表示带有时区的日期和时间,它的使用场景包括但不限于:

  • 处理具有不同时区的日期时间:由于地球是圆形的,不同地理位置处于不同的时区,因此需要在处理日期时间时考虑时区差异。ZonedDateTime可以用于表示带有时区的日期和时间,并能够根据时区进行转换和处理。
  • 日程安排和时间规划:在日程安排和时间规划中,需要考虑不同时区的时间差异。ZonedDateTime可以用于表示会议、活动等的时间和地点,并能够根据参与者所在的时区进行自动转换。
  • 全球化应用:随着全球化的发展,跨时区的交流和合作变得越来越普遍。ZonedDateTime可以用于表示全球范围内的日期和时间,并能够根据不同时区进行格式化和显示。
  • 系统集成和数据交换:在企业级应用和系统集成中,不同系统之间可能存在时区差异。ZonedDateTime可以用于表示系统之间的日期和时间,并能够根据需要进行转换和处理。

总结

与OffsetDateTime的区别

ZonedDateTime与OffsetDateTime的区别主要包括以下几个方面:

  • 时区信息:ZonedDateTime包含时区信息,可能包含城市或地区的信息,而OffsetDateTime只包含时差信息,不包含城市或地区的信息。
  • 创建方式:创建ZonedDateTime和OffsetDateTime类的对象通常通过now()和of()这两个方法完成。通过now()方法所创建的对象表示系统当前的日期时间。而如果通过of()方法创建对象,需要给of()方法传递3部分信息,分别是:日期、时间以及时区。在表示日期时间的参数方面,ZonedDateTime的of()方法的表示时区的参数是ZoneId类型,因此用ZoneRegion类对象和ZoneOffset类对象都可以充当这个参数,而OffsetDateTime的of()方法表示时区的参数类型是ZoneOffset,因此仅能用该类型的对象充当参数。
  • 存储信息:ZonedDateTime类对象中包含localdatetime、zoneid和已解析的zoneoffset三个独立对象的状态,而OffsetDateTime类对象只包含日期和时间字段,以及与GMT/UTC的偏移量。

综上所述,ZonedDateTime和OffsetDateTime都是Java 8中表示日期时间的类,它们在处理日期和时间方面有所不同。ZonedDateTime更适用于处理具有时区信息的日期和时间,而OffsetDateTime则更适用于处理具有偏移量信息的日期和时间。

与LocalDateTime的区别

ZonedDateTime与LocalDateTime的主要区别体现在以下方面:

  • 时区信息:ZonedDateTime包含时区信息,表示一个具有特定时区的日期和时间,而LocalDateTime则没有时区信息,它表示的是一个相对独立的日期和时间。
  • 创建方式:创建ZonedDateTime和LocalDateTime类的对象通常是通过now()和of()这两个方法完成的。通过now()方法所创建的对象表示系统当前的日期时间。而如果通过of()方法创建对象,需要给of()方法传递3部分信息,分别是:日期、时间以及时区。
  • 应用场景:ZonedDateTime更适用于处理具有时区信息的日期和时间,而LocalDateTime则更适用于处理具有偏移量信息的日期和时间。
  • 不可变性:ZonedDateTime是不可变的,即一旦创建了ZonedDateTime对象,其日期和时间信息就不能再被修改。这种不可变性使得ZonedDateTime对象是线程安全的。而LocalDateTime也是不可变的,它同样具有线程安全的特点。

总的来说,ZonedDateTime和LocalDateTime类都是Java 8中表示日期和时间的工具,它们都不可变且线程安全。然而,ZonedDateTime更注重时区信息的处理,而LocalDateTime则不具备这种能力。

      Date、SimpleDateFormat和LocalDate、LocalTime、LocalDateTime、ZonedDateTime、DateTimeFormatter的使用和区别 java1.8引入的新特性中,其中就含有对日期时间的处理,下面我们一起学习和了解。 阅读详情

      相关推荐

      Java8 与日期时间API:讲解Java 8引入的新的日期和时间处理机制,使用LocalDate, LocalDateTime, ZonedDateTime等类

      介绍 Java 8 日期和时间 API 说明在 Java 8 之前存在的问题 讲解为什么需要引入新的日期和时间 API LocalDate 类 介绍 LocalDate 类 示例:如何创建 LocalDate 实例 示例:获取年月日等信息 示例:日期计算、日期比较等操作 LocalDateTime 类 介绍 LocalDateTime 类 示例:如何创建 LocalDateTime 实例 示例:获取日期、时间相关信息 示例:日期、时间的计算、比较等操作 ZonedDateTime 类

      哎 你看的博客 1105

      ZonedDateTime类

      ZonedDateTime类 我们之前在文章《听说你还在用Date类表示时间?》中提到过**“LocalDateTime无法与时间戳进行转换,因为LocalDateTime没有时区,无法确定某一时刻”**。其实LocalDateTime和ZonedDateTime很相似,区别只是LocalDateTime总是表示本地日期和时间,而ZonedDateTime要表示一个带时区的日期和时间。 我们可以简单地把ZonedDateTime理解成LocalDateTime加ZoneId。ZoneId是java.time

      Window_mouse的博客 2万+

      Java8 时间类

      1、介绍 在Java8之前,日期时间API一直被开发者诟病,包括:java.util.Date是可变类型,SimpleDateFormat非线程安全等问题。故此,Java8引入了一套全新的日期时间处理API,新的API基于ISO标准日历系统。 2、名词 时间戳(时刻):时间戳是指格林尼治时间1970年01月01日00时00分00秒到现在的总秒数(毫秒数),可以理解成绝对时间,它与时区无关,不同时区...

      大鹏小站的博客 841

      深入了解Java8新特性-日期时间API之ZonedDateTime类

      ZonedDateTime是Java 8中引入的一个不可变且线程安全的数据类型,用于表示带有时区的日期和时间。与LocalDateTime相比,ZonedDateTime可以存储时区信息,并能够处理模糊的本地日期时间。ZonedDateTime可以表示从本地时间线LocalDateTime到即时时间线Instant之间的日期和时间。两个时间线之间的差异是UTC /格林威治的偏移量,由ZoneOffset表示。在两个时间线之间转换涉及使用从ZoneId访问的ZoneId计算偏移量。 ZonedDateTim

      凡夫编程 4569

      CocosCreator | 自定义启动页之H5

      01 效果对比 默认启动页: 自定义启动页: 02 启动页存在的意义 我们在 creator 中的开发的游戏都是基于 cocos engine,所以在展示我们的游戏之前,是必须要先加载 cocos engine,然后才是我们自己的业务代码 流程图如下: 而构建完成后未精简的 cocos engine 代码为 1.9M 如果再加上物理相关代码的话,一共是2M 别忘了,我们自己的首场景也要加载过程哦 所以,从游戏启动,到真...

      Valiancer 5896

      【各种轮子2】基于Icepak的PCB散热仿真比较

      随着电子产品的集成度越来越高,PCB板的尺寸越来越小,板级芯片散热的问题越来越成为电子工程师的一个重要挑战。对于板级芯片散热,主要依靠工程师对PCB自身的设计进行优化,同时要兼顾系统的尺寸和成本。本文分别从芯片角度和PCB角度进行建模,芯片模型选用QFN封装,PCB模型采用走线导入模型,探讨了芯片结构,PCB铜厚,PCB叠层厚度对芯片散热的影响。

      3669

      Java的日期与时间(十六)java.time.format.DateTimeFormatter

      Java的日期与时间原文链接 作者:Jakob Jenkov 译者:阿为 目录:http://blog.youkuaiyun.com/tjgykhulj/article/details/68952451 (所有译者备注将以此形式出现,删除线表示有争议或不明确的地方)十六、java.time.format.DateTimeFormatterDateTimeFormatter类是Java 8中日期时间功能里

      陀氏 1万+

      AS5600磁编码器选型与安装避坑指南:磁铁形状、间隙距离到底怎么选?(附实测数据)

      本文详细解析了AS5600磁编码器的选型与安装要点,包括磁铁形状、间隙距离等关键参数的选择,并附有实测数据支持。特别针对Arduino和I2C接口的应用场景,提供了硬件选型和机械安装的实用指南,帮助开发者避免常见陷阱,提升系统精度和稳定性。

      weixin_27038245的博客 288

      JAVA11--日期&时间

      日期时间CalendarTimeZoneLocalDateTimDateTimeFormatterDuration和PeriodZonedDateTime时区转换 Java标准库有两套处理日期和时间的API: 一套定义在java.util这个包里面,主要包括Date、Calendar和TimeZone这几个类; 一套新的API是在Java 8引入的,定义在java.time这个包里面,主要包括L...

      LaoChen_ZeroonE 3005

      KTransformers安装笔记 利用docker安装KTransformers

      KTransformers安装笔记 利用docker安装KTransformers

      guoqingru0311的博客 1562

      一文读懂AUTOSAR CAN通信

      在AUTOSAR的分层和模块化架构中,使用PduR(Protocal Data Unit Router)将总线或者网络数据进行抽象,使得上层应用不用关心信号的来源。本文从PduR下层的CAN Interface、CAN Driver和CAN Transceiver Driver模块介绍CAN总线在AUTOSAR架构中的工作机制以及信号的收发等功能。PduR以及COM等上层模块的介绍可以参考公众号内发布的历史文章。

      酒无忧的博客 2494

      Java8 新特性(三)之其他特性

      1、默认方法

      优快云_0622的博客 232

      Visual Studio 2022+Qt6.5.3安装教程+环境配置+创建Qt项目+乱码插件+运行很完美(16岁孩子也能看懂)

      Visual Studio 2022+Qt6.5.3安装教程+环境配置+创建Qt项目+乱码插件+运行很完美(16岁孩子也能看懂)

      Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 1190

      JAVA8新特性

      一.Lambda表达式 使用 Lambda 表达式可以使代码变的更加简洁紧凑,lambda表达式本质上是一个匿名方法。Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)或者把代码看成数据。在最简单的形式中,一个lambda可以由:用逗号分隔的参数列表、–>符号、函数体三部分表示,在某些情况下lambda的函数体会更加复杂,这时可以把函数体放到在一对花括号中,就像在Java中定义普通函数一样。Lambda可以引用类的成员变量与局部变量(如果这些变量不是final的话,它们会被隐含的转

      hellolianhua的博客 134

      2026年中科曙光嵌入式笔试试卷带答案

      2026年中科曙光嵌入式笔试试卷涵盖数字电路、总线协议、时序分析、存储原理及硬件寄存器操作等核心知识点。单选题聚焦SPI/I2C差异、建立/保持时间、ADC作用等基础概念;多选题考察时序约束、非易失存储、BMC功能等综合应用;判断题强化对关键术语的理解;填空题考查基本术语记忆;简答题要求掌握SPI与I2C对比、时序违例后果及BMC管理机制。试题紧扣嵌入式系统开发实际,突出接口协议、时序设计与硬件交互能力,是嵌入式岗位选拔的重要依据。

      Open 23

      淋巴结病理数字玻片读取与处理代码

      Whole-slide images are generally stored in a multi-resolution pyramid structure. 首先安装openslide模块 pip install openslide-python import os.path as osp import openslide from pathlib import Path...

      猫头军师兵书 1276

      时间处理的未来:Java 8全新日期与时间API完全解析

      《Java 8全新日期与时间API完全解析》这篇文章深入探讨了Java 8引入的全新日期与时间API的重要性和功能。文章详细介绍了这些API如何解决传统Java日期时间处理中的常见问题,如可变性和线程安全性。通过引入新的日期时间类(如LocalDate、LocalTime、LocalDateTime等),Java 8使得日期时间处理更加直观和易用,同时提升了性能和灵活性。此外,文章还探讨了如何在项目中逐步迁移旧的日期时间代码到新的API,以及新API如何与现有的Java类库互操作。

      忆~遂愿的博客 8310

      老版QQ原生表情gif动态

      这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

      高级JAVA开发必备技能:java8 新日期时间API((二)JSR-310:常用的日期时间API)(JAVA 小虚竹)

      高级JAVA开发必须掌握技能java8 新日期时间API((二)JSR-310:常用的日期时间API

      小虚竹的专栏 3万+

      复分析 阿尔福斯(Ahlfors) 第三版答案 英文

      答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

      锂电池充电器电路设计 里面有电路

      锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

      Java8日期时间(LocalDate、LocalTime、LocalDateTime、ZonedDateTime)与SpringBoot、MyBatis、MySQL、Oracle的联系

      Java8日期时间(LocalDate、LocalTime、LocalDateTime、ZonedDateTime)与SpringBoot、MyBatis、MySQL、Oracle的联系。

      宋冠巡的博客 4466

      Camera2Demo

      在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

      Java8中新日期时间API(LocalDate\LocalTime\LocalDateTime\ZonedDateTime)

      Java8中新日期时间API(LocalDate\LocalTime\LocalDateTime\ZonedDateTime)

      qq_46274911的博客 1588

      16. Java8-日期API-ZonedDateTime

      ZonedDateTime 是java8 中包含时区的时间类. import org.junit.Test; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; /** * @Description: 除了包含时区信息之外, 和LocalDateTime API...

      Java 程序源 1万+

      【Java 8系列】Java日期时间的新主宰者:LocalDate、LocalTime、LocalDateTime、ZonedDateTime

      热门系列: 【Java 8系列】Stream详解,看这一篇就够啦 【Java 8系列】Lambda 表达式,一看就废 【Java 8系列】Java开发者的判空利器 -- Optional 程序人生,精彩抢先看 1、前言 本系列一直在分享Java8的新增特性与API,今天和大家一起扒一扒Java的新时间类库:java.time; 之前我在往期博文:【Java编程系列】Java判断世界各时区的夏令时、冬令时中就有提到过,为什么现在不适用Date时间类,而改...

      Yangy的博客 4574

      Java8中新的日期时间API

      Java 8 引入了全新的 java.time 日期时间 API,解决了传统 Date、Calendar 等类的设计缺陷。新 API 具有线程安全、不可变、易用性高等特点。核心类包括:Clock 时钟类、Instant 时间戳类,以及 LocalDate、LocalTime、LocalDateTime 等日期时间处理类。相比旧 API,新 API 解决了月份从0开始、年份偏移1900等问题,并提供了更丰富的操作方法。

      墨言的博客 1万+

      高级JAVA开发必备技能:java8 新日期时间API((二)JSR-310:常用的日期时间API)(JAVA 小虚竹

      介绍下java8API比较常用的日期时间API,按java.timeClock:时钟Instant:瞬间时间。LocalDate:本地日期。只有表示年月日LocalDateTime:本地日期时间,LocalDate+LocalTimeLocalTime:本地时间,只有表示时分秒OffsetDateTime:有时间偏移量的日期时间(不包含基于ZoneRegion的时间偏移量)OffsetTime:有时间偏移量的时间。

      2401_84562425的博客 1181

      Java 8 新特性—日期时间 API

      由于地球自转,不同经度上的地方会在不同时刻经历日出和日落,因此当你在一个地方看到太阳高悬在天空中时,在另一个地方可能是夜晚。当你 9 点起来上班时,别人可能刚刚吃完晚饭准备带老婆孩子去遛弯,所以我们需要创建时区机制,来保证能更合理地安排生产生活。时区是地球上的不同区域,每个区域都使用统一的时间标准,使人们能够在不同地方协调时间。时区基于经度划分,地球被分成24个主要时区,每个时区大致相当于地球上的一个经度带。每个时区都有自己的标准时间,该时间是该时区内所有地方的参考时间。

      smart_an的专栏 1318

      java.time.ZonedDateTime类

      类表示ISO-8601。

      unber的博客 1162
      上一篇: 深入Java8-日期时间API:OffsetDateTime类
      下一篇: 深入Java8-日期时间API:TemporalQuery、TemporalQueries类
      昭武归尘
      博客等级 码龄8年 92粉丝 32原创
      评论
      成就一亿技术人!
      拼手气红包6.0元
      还能输入1000个字符
       
       条评论被折叠 查看
      添加红包

      请填写红包祝福语或标题

      个

      红包个数最小为10个

      元

      红包金额最低5元

      当前余额3.43元 前往充值 >
      需支付:10.00元
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付元
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值