深入了解Java8新特性-日期时间API之ZonedDateTime类
阅读建议
嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:
- 本篇文章大概19000多字,预计阅读时间长需要10分钟以上。
- 本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
- 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。
注意
本文编写的单元测试是基于java11,具体的版本号是:11.0.19
关于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/ShanghaiZonedDateTime 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);//输出结果:trueSystem.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);//输出结果:trueSystem.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);//输出结果:2023System.out.println(yearOfYear);//输出结果:2023System.out.println(month);//输出结果:11System.out.println(day);//输出结果:29System.out.println(dayOfYear);//输出结果:333System.out.println(offset);//输出结果:+08:00
}
ZonedDateTime#getZone(...)
ZonedDateTime#getZone() 用于获取该对象的时区。此方法返回一个 ZoneId 对象,表示 ZonedDateTime 对象的时区。ZoneId 是 Java 8 中表示时区的类。
@Testpublic 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:12LocalDate localDate = zonedDateTime.toLocalDate();System.out.println(localDate);//输出结果:2023-11-29LocalTime 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);//输出结果:2023System.out.println(monthValue);//输出结果:11System.out.println(dayOfMonth);//输出结果:29System.out.println(dayOfYear);//输出结果:333System.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则不具备这种能力。
相关文章:

深入了解Java8新特性-日期时间API之ZonedDateTime类
阅读建议 嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议: 本篇文章大概19000多字,预计阅读时间长需要10分钟以上。本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章&…...
使用Vue写一个日期选择器
在 Vue 中实现日期选择器的方法有很多,下面提供一个简单的实现方法。 首先,在需要使用日期选择器的组件中引用 Vue 和 date-fns 库,date-fns 库是一个轻量级的 JavaScript 时间日期工具库,可以方便地处理日期的格式化和计算。 &…...

19、pytest通过mark标记测试函数
官方实例 [pytest] markers slow:marks tests as slow(deselect with -m "not slow")serial# content of test_mark.py import pytestpytest.mark.slow def test_mark_function():print("test_mark_function was invoked")assert 0解读与实操 通过使用p…...

Linux环境变量与命令行参数
Linux环境变量与命令行参数 一.命令行参数1.语法2.应用1:简易计算器 二.环境变量1.环境变量的概念2.环境变量的作用3.进一步理解环境变量的作用4.常见环境变量5.导出环境变量(添加环境变量)6.环境变量的特性7.另一种获取环境变量的方式8.小功能:用于身份验证的代码9.补充:第三种…...
jQuery实现3D轮播图
通过CSS3的3D变换和jQuery Transit插件实现了一个3D旋转的图片轮播效果 HTML部分: div id“banner”:定义了一个id为"banner"的div标签,作为图片轮播的容器。 ul: 在"banner"中定义了一个无序列表,每个列表项…...
Java面试题(每天10题)-------连载(43)
目录 Spring篇 1、请举例说明Qualifier注解 2、构造方法注入和设值注入有什么区别? 3、Spring框架中有哪些不同类型的事件? 4、FileSystemResource和ClassPathResource有什么区别? 5、Spring框架中都用到了哪些设计模式? 6…...
Python高级数据结构——并查集(Disjoint Set)
Python中的并查集(Disjoint Set):高级数据结构解析 并查集是一种用于处理集合的数据结构,它主要支持两种操作:合并两个集合和查找一个元素所属的集合。在本文中,我们将深入讲解Python中的并查集࿰…...
pytorch学习9-优化器学习
系列文章目录 pytorch学习1-数据加载以及Tensorboard可视化工具pytorch学习2-Transforms主要方法使用pytorch学习3-torchvisin和Dataloader的使用pytorch学习4-简易卷积实现pytorch学习5-最大池化层的使用pytorch学习6-非线性变换(ReLU和sigmoid)pytorc…...

MySQL之锁
MySQL之锁 锁是计算机在执行多线程或线程时用于并发访问同一共享资源时的同步机制,MySQL中的锁是在服务器层或者存储引擎层实现的,保证了数据访问的一致性与有效性 MySQL锁可以按模式分类为:乐观锁与悲观锁。 按粒度分可以分为全局锁、表级锁…...

今日现货黄金最新建议
近期现货黄金价格再度逼近历史高位,很多本来在场外观望的投资者,都纷纷希望进场一试身手。然而大涨大跌的行情并不是很适合新手投资者参与,如果大家还没做好技术上的准备,可以多听听正规交易平台的专业人士的意见。 在正式入市之前…...

基于混沌算法的图像加密解密系统
1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义: 随着信息技术的迅猛发展,图像的传输和存储已经成为现代社会中不可或缺的一部分。然而,随着互联网的普及和信息的快速传播&am…...

vscode插件离线下载
离线下载插件地址:https://marketplace.visualstudio.com/VSCode...

第二十一章总结
一、网络通信: 1.网络程序设计基础:网络程序设计编写的是与其他计算机进行通信的程序。 1.1局域网与互联网:为了实现两台计算机的通信,必须用一个网络线路连接两台计算机 2.网络协议:网络协议规定了计算机之间连接的…...

查看端口占用并杀死进程
1.安装查看工具 sudo yum install net-tools 2.查看占用情况 netstat -tunlp | grep 8089 3.杀死进程 kill -9 227...

前后端数据传输格式(上)
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 作为后端,写…...
maven的package和install命令有什么区别以及Maven常用命令与GAV坐标与Maven依赖范围与Maven依赖传递与依赖排除与统一声明版本号
maven的package和install命令有什么区别以及Maven常用命令与GAV坐标与Maven依赖范围与Maven依赖传递与依赖排除与统一声明版本号 一: maven的package和install命令有什么区别 一般都与clean命令结合使用 mvn package 生成target目录,编译、测试代码,…...

【动手学深度学习】(六)权重衰退
文章目录 一、理论知识二、代码实现2.1从零开始实现2.2简洁实现 【相关总结】 主要解决过拟合 一、理论知识 1、使用均方范数作为硬性限制(不常用) 通过限制参数值的选择范围来控制模型容量 通常不限制偏移b 小的意味着更强的正则项 使用均方范数作为柔…...

动手学习深度学习-跟李沐学AI-自学笔记(3)
一、深度学习硬件-CPU和GPU 芯片:Intel or AMD 内存:DDR4 显卡:nVidia 芯片可以和GPU与内存通信 GPU不能和内存通信 1. CPU 能算出每一秒能运算的浮点运算数(大概0.15左右) 1.1 提升CPU利用率 1.1.1 提升缓存…...
3.2 Puppet 和 Chef 的比较与应用
Puppet 和 Chef 的比较与应用 文章目录 Puppet 和 Chef 的比较与应用Puppet 和 Chef 简介工作原理对比**模块化的重要性**: Puppet 和 Chef 简介 介绍 Puppet 和 Chef 这两个流行的配置管理工具的背景和用途。强调它们的共同目标:实现自动化的系统配置和…...
promise使用示例
下面是一个 Promise 使用示例,通过 Promise 实现异步操作的链式调用: const getUser (userId) > {return new Promise((resolve, reject) > {// 模拟异步请求setTimeout(() > {const users [{ id: 1, name: Alice },{ id: 2, name: Bob },{ …...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...