嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:
本文编写的单元测试是基于java11,具体的版本号是:11.0.19
ZonedDateTime是Java 8中引入的一个不可变且线程安全的数据类型,用于表示带有时区的日期和时间。与LocalDateTime相比,ZonedDateTime可以存储时区信息,并能够处理模糊的本地日期时间。
ZonedDateTime可以表示从本地时间线LocalDateTime到即时时间线Instant之间的日期和时间。两个时间线之间的差异是UTC /格林威治的偏移量,由ZoneOffset表示。在两个时间线之间转换涉及使用从ZoneId访问的ZoneId计算偏移量。
ZonedDateTime的常用方法包括获取年份、月份、日期、小时、分钟、秒等信息的get方法,以及计算两个日期之间的差值的minus方法等。ZonedDateTime还提供了用于获取当前日期和时间的now方法,以及用于将ZonedDateTime转换为其它日期/时间类型的toLocalDate、toLocalTime等方法。
需要注意的是,ZonedDateTime在进行时区转换时可能会遇到夏令时调整的情况,此时需要使用正确的时区信息以避免错误的出现。另外,在处理涉及时区的日期和时间时,需要考虑时区偏移量以及时间线之间的差异等问题。
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]
- }
- @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() 用于从其他时间单位(如 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 对象。这个方法接受一个字符串参数,并尝试将其解析为
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(...) 用于确定当前时间是否支持给定的时间字段。这个方法接受一个 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(...) 是 用于获取给定时间字段的范围。这个方法接受一个 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
- }
这些方法都可用于处理和操作具有时区信息的时间,但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() 用于获取该对象的时区。此方法返回一个 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
- }
- @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()方法、toLocalDate()方法和toLocalTime()方法分别用于返回该日期时间对象的LocalDateTime部分、LocalDate部分和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
- }
这些方法的作用是根据给定的时间点获取不同的时间单位信息。主要的使用场景:
- @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
- }
这些方法的使用场景包括但不限于以下情况:
- @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(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]
- }
- @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]
- }
- @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 对象相关的信息。该方法接受一个 TemporalQuery 参数,用于指定要查询的信息类型。TemporalQuery 是一个函数式接口,用于从给定的时间对象中提取所需的信息。
- @Test
- public void test16() {
- ZonedDateTime zonedDateTime = ZonedDateTime.of(2023, 11, 29, 13, 32, 12, 0, ZoneId.of("Asia/Shanghai"));
- TemporalQuery
temporalQuery=item->item.get(ChronoField.DAY_OF_YEAR); - Integer dayOfYear = zonedDateTime.query(temporalQuery);
- System.out.println(dayOfYear); //输出结果:333
- }
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() 用于将当前对象的时间信息按照指定的格式进行格式化,并返回一个字符串表示。该方法接受一个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() 用于将当前对象转换为一个 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与OffsetDateTime的区别主要包括以下几个方面:
综上所述,ZonedDateTime和OffsetDateTime都是Java 8中表示日期时间的类,它们在处理日期和时间方面有所不同。ZonedDateTime更适用于处理具有时区信息的日期和时间,而OffsetDateTime则更适用于处理具有偏移量信息的日期和时间。
ZonedDateTime与LocalDateTime的主要区别体现在以下方面:
总的来说,ZonedDateTime和LocalDateTime类都是Java 8中表示日期和时间的工具,它们都不可变且线程安全。然而,ZonedDateTime更注重时区信息的处理,而LocalDateTime则不具备这种能力。