当前位置: 首页 > news >正文

深入了解Java8新特性-日期时间API:OffsetDateTime类

阅读建议

嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:

  1. 本篇文章大概24000多字,预计阅读时间长需要20分钟。
  2. 本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
  3. 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。

注意

本文编写的单元测试是基于java11,具体的版本号是:11.0.19

关于OffsetDateTime

OffsetDateTime是Java 8中引入的一个不可变且线程安全的日期时间数据类型,用于表示带有时区偏移的日期和时间。因为它是一种不可变的数据类型,所以在进行比较或传递时不会发生变化。

OffsetDateTime可以表示从本地时间线LocalDateTime到即时时间线Instant之间的日期和时间。两个时间线之间的差异是UTC /格林威治的偏移量,由ZoneOffset表示。在两个时间线之间转换涉及使用从ZoneId访问的ZoneId计算偏移量。在处理带有时区偏移的日期和时间时,使用OffsetDateTime可以方便地表示和操作具有特定时区偏移的日期和时间,避免时区转换带来的问题。

而时区是为了克服时间上的混乱,在1884年在华盛顿召开的一次国际经度会议上,规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为中时区(零时区)、东1-12区,西1-12区。每个时区横跨经度15度,时间正好是1小时。每个时区的中央经线上的时间就是这个时区内统一采用的时间,称为区时,相邻两个时区的时间相差1小时。

中国横跨东五区至东九区5个时区,自西向东可依次分为东六区、东七区、东八区、东九区、东十区。为了使用方便,中国采用首都北京所在的东八区的区时作为全国统一使用时间,也就是北京时间。

核心方法

OffsetDateTime#now()

OffsetDateTime#now()是Java 8中 java.time.OffsetDateTime类的一个非常简单方法,这个方法不需要任何参数,返回表示当前日期和时间的 OffsetDateTime 对象。

@Test
public void test() {OffsetDateTime offsetDateTime = OffsetDateTime.now();System.out.println(offsetDateTime);//输出结果:2023-11-27T18:15:42.924290700+08:00
}

OffsetDateTime#of(...)、OffsetDateTime#ofInstant(...)

OffsetDateTime#of(...)和OffsetDateTime#ofInstant(...)都是用于创建和操作具有偏移量的日期和时间对象的工具,区别在于接受参数类型上:

  • OffsetDateTime#of(...):有多个重载方法,可以接受年、月、日、小时、分钟、秒、纳秒和偏移量创建OffsetDateTime的实例,可以接受一个LocalDateTime实例和偏移量创建OffsetDateTime的实例,也可以接受LocalDate、LocalTime和偏移量,创建OffsetDateTime的实例;当你需要创建一个具有明确日期和时间,并且需要表示与UTC的偏移量的OffsetDateTime对象时,可以使用此方法。例如,如果你正在处理具有特定时间戳的金融交易,或者需要表示在特定时间点上的事件,这个方法可能会非常有用。
  • OffsetDateTime#ofInstant(...): 此方法用于根据指定的Instant和ZoneId创建OffsetDateTime的实例。当你已经有一个表示瞬时时间的Instant对象,并且需要将这个时间与特定的时区关联起来时,可以使用此方法。例如,如果你正在处理全球事件,并且需要根据不同时区来解释和显示时间信息,这个方法会非常有用。或者,如果你正在处理从外部源(如数据库或API)接收的日期和时间信息,并且需要将其转换为本地时区的时间表示,这个方法也可以使用。
@Test
public void test2() {LocalDateTime localDateTime = LocalDateTime.of(2023, 11, 27, 18, 42, 56);//北京属于东八区OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(8));//纽约属于西五区OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(-5));System.out.println(offsetDateTime);//输出结果:2023-11-27T18:42:56+08:00Duration between = Duration.between(offsetDateTime, offsetDateTime1);long hours = between.toHours();System.out.println(hours);//以美国纽约时间与中国北京时间相差13个小时,输出结果:13Instant instant = Instant.ofEpochSecond(1L);System.out.println(instant);//输出结果:1970-01-01T00:00:01ZOffsetDateTime offsetDateTime2 = OffsetDateTime.ofInstant(instant, ZoneId.systemDefault());System.out.println(offsetDateTime2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));//输出结果:1970-01-01 08:00:01,这与上面的输出结果相差了8个小时,原因就在于ZoneId.systemDefault()获取了系统默认时区,中国采用东八区时区,因此与格林尼治时间相差了8小时
}

OffsetDateTime#from(...)

OffsetDateTime#from(...)可以将其他类型的日期和时间对象转换为 OffsetDateTime 对象。这个方法接受一个 TemporalAccessor 对象作为参数,并根据该对象中的日期和时间信息创建一个新的 OffsetDateTime 对象。当你需要将其他类型的日期和时间对象转换为 OffsetDateTime 对象时,可以使用这个方法。

@Test
public void test3() {LocalDateTime localDateTime = LocalDateTime.of(2023, 11, 27, 18, 42, 56);ZoneOffset zoneOffset = ZoneOffset.ofHours(8);ZonedDateTime zonedDateTime = localDateTime.atZone(zoneOffset);OffsetDateTime from = OffsetDateTime.from(zonedDateTime);System.out.println(from);//2023-11-27T18:42:56+08:00
}

OffsetDateTime#parse(...)

OffsetDateTime#parse() 的主要功能是将字符串解析为 OffsetDateTime 对象,主要是用于将字符串表示的日期和时间转换为 OffsetDateTime 对象时,它接受一个字符串作为参数,并尝试将其解析为 OffsetDateTime,解析过程会考虑本地时区,并将字符串解析为具有偏移量的日期和时间。

@Test
public void test4() {String dateTimeStr = "2023-11-28T09:45:56+08:00";OffsetDateTime from = OffsetDateTime.parse(dateTimeStr);System.out.println(from);//输出结果:2023-11-28T09:45:56+08:00
}

OffsetDateTime#isSupported(...)

OffsetDateTime#isSupported()用于检查是否支持特定的单位或字段。如果支持,方法将返回 true;如果不支持,方法将返回 false。主要的使用场景:在执行日期时间运算之前,可以使用该方法检查是否支持所使用的单位或字段,以避免因操作不支持的单位或字段而引发异常。

@Test
public void test5() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));boolean supported1 = offsetDateTime.isSupported(ChronoField.YEAR);boolean supported2 = offsetDateTime.isSupported(ChronoUnit.HOURS);System.out.println(supported1);//输出结果:trueSystem.out.println(supported2);//输出结果:true
}

OffsetDateTime#range(...)

OffsetDateTime#range()方法是用于获取特定字段的范围的ValueRange对象。该方法的功能作用是根据作为参数传递的字段,获取该字段的有效值范围。具体来说,该方法接受一个参数,即要查询范围的字段,然后返回一个ValueRange对象,该对象表示该字段的有效值范围。如果此方法不支持该字段,则可能引发异常。

使用场景包括需要确定特定字段的范围和有效值的场景。例如,在数据库查询中,可以使用该方法来获取特定字段的取值范围,从而构建更精确的查询条件。在日期时间处理中,可以使用该方法获取特定日期时间字段的有效范围,以便进行日历计算、时间间隔计算等操作。

需要注意的是,该方法仅对OffsetDateTime对象支持的字段返回ValueRange对象。因此,如果查询的字段不受支持,此方法可能会引发异常。在使用时需要确保查询的字段是受支持的,以避免出现异常情况。

@Test
public void test6() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));ValueRange range = offsetDateTime.range(ChronoField.DAY_OF_MONTH);System.out.println(range.getMinimum());//输出结果:1System.out.println(range.getMaximum());//输出结果:30
}

OffsetDateTime#get(...)、OffsetDateTime#getLong(...)、OffsetDateTime#getOffset(...)、OffsetDateTime#getYear(...)、OffsetDateTime#getMonthValue(...)、OffsetDateTime#getMonth(...)、OffsetDateTime#getDayOfMonth(...)、OffsetDateTime#getDayOfYear(...)、OffsetDateTime#getDayOfWeek(...)、OffsetDateTime#toLocalTime(...)、OffsetDateTime#getHour(...)、OffsetDateTime#getMinute(...)、OffsetDateTime#getSecond(...)、OffsetDateTime#getNano(...)

这些方法主要用于获取OffsetDateTime对象中指定字段的值,需要注意的是,该方法仅对受支持的字段返回有效值,对于不支持的字段可能会引发异常。因此,在使用时需要确保查询的字段是受支持的,以避免出现异常情况。

  • OffsetDateTime#get()方法的功能作用是从该日期时间中获取指定字段的值。它接受一个参数,即要获取的字段,然后返回该字段的值。使用场景包括需要获取日期时间中特定字段的值的情况。例如,在日期时间处理中,可以使用该方法获取日期、时间、时区等信息,以便进行进一步的处理和计算。
  • OffsetDateTime#getLong()方法的功能作用是从该日期时间中获取long形式的指定字段的值。它接受一个参数,即要获取的字段,然后返回该字段的值。使用场景包括需要获取日期时间中特定字段的长整型值的情况。例如,在日期时间处理中,可以使用该方法获取日期、时间等信息,以便进行进一步的处理和计算。
  • OffsetDateTime#getOffset()方法的功能作用是获取该日期的偏移量。它返回一个ZoneOffset对象,表示该日期的偏移量。使用场景包括需要获取日期时间的偏移量的情况。例如,在日期时间处理中,可以使用该方法获取偏移量信息,以便进行日历计算、时间间隔计算等操作。
  • OffsetDateTime#getYear()方法的功能作用是获取该日期的年份。使用场景包括需要获取日期时间的年份的情况。例如,在日期时间处理中,可以使用该方法获取年份信息,以便进行日历计算、时间间隔计算等操作。
  • OffsetDateTime#getMonthValue()方法的功能作用是获取该日期的月份的值。使用场景包括需要获取日期时间的月份的情况。例如,在日期时间处理中,可以使用该方法获取月份信息,以便进行日历计算、时间间隔计算等操作。
  • OffsetDateTime#getMonth()方法的功能作用是获取该日期的月份的名称。它返回一个String对象,表示该月份的名称。使用场景包括需要获取日期时间的月份名称的情况。例如,在日期时间处理中,可以使用该方法获取月份名称信息,以便进行日历显示、报告生成等操作。
  • OffsetDateTime#getDayOfMonth()方法的功能作用是获取该日期的日期的值。使用场景包括需要获取日期时间的日期的的情况。例如,在日期时间处理中,可以使用该方法获取日期信息,以便进行日历计算、时间间隔计算等操作。
  • OffsetDateTime#getDayOfYear()方法的功能作用是获取该日期的年份的第几天。它返回一个int值,表示该日期是当年的第几天。使用场景包括需要确定日期是当年的第几天的情况。例如,在日历程序或报告生成中,可以使用该方法获取日期在一年中的天数信息。
  • OffsetDateTime#getDayOfWeek()方法的功能作用是获取该日期是星期几。它返回一个int值,表示星期几,其中1代表星期天,2代表星期一,以此类推。使用场景包括需要确定日期是星期几的情况。例如,在日历程序或报告生成中,可以使用该方法获取星期信息。
  • OffsetDateTime#toLocalTime()方法的功能作用是将该日期时间转换为LocalTime对象。它返回一个新的LocalTime对象,表示该日期时间的本地时间部分。使用场景包括需要将日期时间转换为LocalTime对象进行进一步处理的情况。例如,在需要只处理时间部分而不涉及日期时,可以使用该方法将日期时间转换为LocalTime对象进行处理。
  • OffsetDateTime#getHour()方法的功能作用是获取该日期时间的时区的的小时数。它返回一个int值,表示小时数。使用场景包括需要确定日期时间的时区的小时数的情况。例如,在时区转换或时间计算中,可以使用该方法获取时区的小时信息。
  • OffsetDateTime#getMinute()方法的功能作用是获取该日期时间的时区的分钟数。它返回一个int值,表示分钟数。
@Test
public void test7() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));int year = offsetDateTime.get(ChronoField.YEAR);System.out.println(year);//输出结果:2023int month = offsetDateTime.get(ChronoField.MONTH_OF_YEAR);System.out.println(month);//输出结果:11int day = offsetDateTime.get(ChronoField.DAY_OF_MONTH);System.out.println(day);//输出结果:28int hour = offsetDateTime.get(ChronoField.HOUR_OF_DAY);System.out.println(hour);//输出结果:9int minutes = offsetDateTime.get(ChronoField.MINUTE_OF_HOUR);System.out.println(minutes);//输出结果:46int second = offsetDateTime.getSecond();System.out.println(second);//输出结果:56int year1 = offsetDateTime.getYear();System.out.println(year1);//输出结果:2023int month1 = offsetDateTime.getMonthValue();System.out.println(month1);//输出结果:11int hour1 = offsetDateTime.getHour();System.out.println(hour1);//输出结果:9int dayOfYear = offsetDateTime.getDayOfYear();int dayOfMonth = offsetDateTime.getDayOfMonth();int dayOfWeek = offsetDateTime.getDayOfWeek().getValue();System.out.println(dayOfYear);//输出结果:332System.out.println(dayOfMonth);//输出结果:28System.out.println(dayOfWeek);//输出结果:2
}

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

  • OffsetDateTime#toLocalDateTime()的功能作用是将 OffsetDateTime 对象转换为 LocalDateTime 对象。使用场景:当你需要将带有时区偏移的日期时间转换为不带有时区偏移的日期时间对象时,可以使用此方法。这在你只需要处理没有时区偏移的日期时间时非常有用。
  • OffsetDateTime#toLocalDate()的功能作用是将 OffsetDateTime 对象转换为 LocalDate 对象,忽略时间部分。使用场景:当你需要将带有时区偏移的日期时间转换为日期部分,并忽略时间部分时,可以使用此方法。例如,在处理日历事件或日期相关操作时,可能只需要日期信息而不需要时间信息。
  • OffsetDateTime#toLocalTime()的功能作用:将 OffsetDateTime 对象转换为 LocalTime 对象,忽略日期部分。使用场景:当你需要将带有时区偏移的时间转换为时间部分,并忽略日期部分时,可以使用此方法。例如,在处理具体时间段或时间相关操作时,可能只需要时间信息而不需要日期信息。

需要注意的是,这些方法都可能抛出 DateTimeException 异常,如果输入的 OffsetDateTime 对象包含无效的日期或时间信息,或者不支持某些字段。因此,在使用这些方法时,需要确保输入的 OffsetDateTime 对象是有效和受支持的。

@Test
public void test8() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));LocalDateTime localDateTime = offsetDateTime.toLocalDateTime();System.out.println(localDateTime);//输出结果:2023-11-28T09:46:56LocalDate localDate = offsetDateTime.toLocalDate();System.out.println(localDate);//输出结果:2023-11-28LocalTime localTime = offsetDateTime.toLocalTime();System.out.println(localTime);//输出结果:09:46:56
}

OffsetDateTime#with(...)、OffsetDateTime#withYear(...)、OffsetDateTime#withMonth(...)、OffsetDateTime#withDayOfMonth(...)、OffsetDateTime#withDayOfYear(...)、OffsetDateTime#withHour(...)、OffsetDateTime#withMinute(...)、OffsetDateTime#withSecond(...)、OffsetDateTime#withNano(...)、OffsetDateTime#withOffsetSameLocal(...)、OffsetDateTime#withOffsetSameInstant(...)

这些方法都允许开发者以特定的粒度(年、月、日、小时、分钟、秒和纳米秒)调整一个给定的OffsetDateTime实例。这些方法使得开发者能够根据特定的需求(如改变日期或时间)来操作和修改日期和时间数据。

具体如下:

  • OffsetDateTime#with(): 该方法用于使用TemporalAdjuster调整此OffsetDateTime,并在调整后返回调整后的OffsetDateTime的副本。使用指定的调整器策略对象进行调整。此OffsetDateTime实例是不可变的,不受此方法调用的影响。
  • OffsetDateTime#withYear(): 该方法返回此OffsetDateTime的副本,其年份按参数中的指定进行了更改。参数为单个year,范围可以从MIN_YEAR到MAX_YEAR。返回的日期带有请求的年份,而不是null。如果年份值无效,将引发DateTimeException。
  • OffsetDateTime#withMonth(): 该方法返回此OffsetDateTime的副本,其月份按参数中的指定进行了更改。参数为单个month,范围从1到12。返回的日期带有请求的月份。
  • OffsetDateTime#withDayOfMonth(): 该方法返回此OffsetDateTime的副本,其日按参数中的指定进行了更改。参数为单个dayOfMonth,范围从1到月份的天数。返回的日期带有请求的日。
  • OffsetDateTime#withDayOfYear(): 该方法返回此OffsetDateTime的副本,其一年中的日子按参数中的指定进行了更改。参数为单个dayOfYear,范围从1到365或366(取决于年份是否为闰年)。返回的日期带有请求的日。
  • OffsetDateTime#withHour(): 该方法返回此OffsetDateTime的副本,其小时按参数中的指定进行了更改。参数为单个hour,范围从0到23。返回的日期带有请求的小时。
  • OffsetDateTime#withMinute(): 该方法返回此OffsetDateTime的副本,其分钟按参数中的指定进行了更改。参数为单个minute,范围从0到59。返回的日期带有请求的分钟。
  • OffsetDateTime#withSecond(): 该方法返回此OffsetDateTime的副本,其秒数按参数中的指定进行了更改。参数为单个second,范围从0到59。返回的日期带有请求的秒数。
  • OffsetDateTime#withNano(): 该方法返回此OffsetDateTime的副本,其纳米秒按参数中的指定进行了更改。参数为单个nanoOfSecond,范围从0到999999999。返回的日期带有请求的纳米秒数。
  • OffsetDateTime#withOffsetSameLocal(): 该方法返回一个具有相同本地时间的OffsetDateTime,但时间偏移量可能不同。使用指定的偏移量对此OffsetDateTime进行修改,并返回修改后的实例。
  • OffsetDateTime#withOffsetSameInstant(): 该方法返回一个具有相同即时时间的OffsetDateTime,但可能具有不同的本地时间。使用指定的偏移量对此OffsetDateTime进行修改,并返回修改后的实例。

需要注意的是,这些方法大多数情况下不会改变原始的OffsetDateTime实例,而是返回一个新的实例,原始实例依然保持不变。这是由于Java中大多数不可变类(如String、Integer等)的设计思路是一致的。

@Test
public void test9() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));OffsetDateTime with = offsetDateTime.with(ChronoField.MONTH_OF_YEAR, 10);System.out.println(with);//输出结果:2023-10-28T09:46:56+08:00TemporalAdjuster temporalAdjuster = item -> item.plus(1, ChronoUnit.HOURS);OffsetDateTime with1 = offsetDateTime.with(temporalAdjuster);System.out.println(with1);//输出结果:2023-11-28T10:46:56+08:00OffsetDateTime offsetDateTime1 = offsetDateTime.withYear(2020);System.out.println(offsetDateTime1);//输出结果:2020-11-28T09:46:56+08:00OffsetDateTime offsetDateTime2 = offsetDateTime.withMonth(2);System.out.println(offsetDateTime2);//输出结果:2023-02-28T09:46:56+08:00OffsetDateTime offsetDateTime3 = offsetDateTime.withDayOfMonth(25);System.out.println(offsetDateTime3);//输出结果:2023-11-25T09:46:56+08:00OffsetDateTime offsetDateTime4 = offsetDateTime.withOffsetSameInstant(ZoneOffset.ofHours(-13));System.out.println(offsetDateTime4);//输出结果:2023-11-27T12:46:56-13:00,什么意思呢?意思是:同一时刻北京时间是2023-11-28T09:46:56+08:00,而同一时刻的纽约时间是:2023-11-27T12:46:56-13:00OffsetDateTime offsetDateTime5 = offsetDateTime.withOffsetSameLocal(ZoneOffset.ofHours(-13));System.out.println(offsetDateTime5);//输出结果:2023-11-28T09:46:56-13:00
}

OffsetDateTime#truncatedTo(...)

OffsetDateTime#truncatedTo()用于将当前OffsetDateTime对象的时间部分截断到给定的时间单位,例如分钟、小时、天等。截断后的OffsetDateTime对象将不再包含被截断单位之前的时间信息。

使用场景:

  • 需要截断日期时间时:在一些特定的应用场景中,可能需要对日期时间进行截断操作。例如,在进行统计或数据分析时,可能只需要日期时间中的某一部分信息,而不需要保留完整的时间信息。在这种情况下,可以使用OffsetDateTime#truncatedTo()方法将日期时间截断到所需的时间单位。
  • 需要进行时间运算时:在进行时间运算时,如计算两个日期时间之间的差值或进行日期的加减运算等,可以将日期时间截断到分钟或小时级别,以避免因毫秒级的时间差异而产生误差。例如,可以使用OffsetDateTime#truncatedTo()方法将日期时间截断到分钟级别,然后进行加减运算,以实现精确到分钟的日期时间计算。
@Test
public void test10() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));System.out.println(offsetDateTime);//输出结果:2023-11-28T09:46:56+08:00OffsetDateTime offsetDateTime1 = offsetDateTime.truncatedTo(ChronoUnit.DAYS);System.out.println(offsetDateTime1);//输出结果:2023-11-28T00:00+08:00
}

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

OffsetDateTime#plus()可以在当前OffsetDateTime对象的基础上加上指定的时间长度。这个方法有很多重载版本,可以支持不同的时间单位,包括年(Years)、月(Months)、周(Weeks)、天(Days)、小时(Hours)、分钟(Minutes)、秒(Seconds)和纳秒(Nanos)。这些方法都返回一个新的OffsetDateTime对象,表示添加了指定时间长度后的日期和时间。它们不会改变原始的OffsetDateTime对象。如果添加的时间长度为负数,则会相应地减去时间长度。注意,如果程序超出支持的数据和时间范围,则可能会引发DateTimeException异常。

具体如下:

  • OffsetDateTime#plusYears(long years):在当前OffsetDateTime对象的基础上加上指定的年数。这个方法接受一个长整型参数,表示要添加的年数。使用场景包括需要计算未来某一时间点在特定年数后的日期和时间。
  • OffsetDateTime#plusMonths(long months):在当前OffsetDateTime对象的基础上加上指定的月数。这个方法接受一个长整型参数,表示要添加的月数。使用场景包括需要计算未来某一时间点在特定月数后的日期和时间。
  • OffsetDateTime#plusWeeks(long weeks):在当前OffsetDateTime对象的基础上加上指定的周数。这个方法接受一个长整型参数,表示要添加的周数。使用场景包括需要计算未来某一时间点在特定周数后的日期和时间。
  • OffsetDateTime#plusDays(long days):在当前OffsetDateTime对象的基础上加上指定的天数。这个方法接受一个长整型参数,表示要添加的天数。使用场景包括需要计算未来某一时间点在特定天数后的日期和时间。
  • OffsetDateTime#plusHours(long hours):在当前OffsetDateTime对象的基础上加上指定的小时数。这个方法接受一个长整型参数,表示要添加的小时数。使用场景包括需要计算未来某一时间点在特定小时数后的日期和时间。
  • OffsetDateTime#plusMinutes(long minutes):在当前OffsetDateTime对象的基础上加上指定的分钟数。这个方法接受一个长整型参数,表示要添加的分钟数。使用场景包括需要计算未来某一时间点在特定分钟数后的日期和时间。
  • OffsetDateTime#plusSeconds(long seconds):在当前OffsetDateTime对象的基础上加上指定的秒数。这个方法接受一个长整型参数,表示要添加的秒数。使用场景包括需要计算未来某一时间点在特定秒数后的日期和时间。
  • OffsetDateTime#plusNanos(long nanos):在当前OffsetDateTime对象的基础上加上指定的纳秒数。这个方法接受一个长整型参数,表示要添加的纳秒数。使用场景包括需要计算未来某一时间点在特定纳秒数后的日期和时间。
@Test
public void test11() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));OffsetDateTime offsetDateTime1 = offsetDateTime.plus(1, ChronoUnit.YEARS);System.out.println(offsetDateTime1);//输出结果:2024-11-28T09:46:56+08:00OffsetDateTime offsetDateTime2 = offsetDateTime.plus(Period.ofYears(2));System.out.println(offsetDateTime2);//输出结果:2025-11-28T09:46:56+08:00OffsetDateTime offsetDateTime3 = offsetDateTime.plusYears(2);System.out.println(offsetDateTime3);//输出结果:2025-11-28T09:46:56+08:00OffsetDateTime offsetDateTime4 = offsetDateTime.plusMonths(1);System.out.println(offsetDateTime4);//输出结果:2023-12-28T09:46:56+08:00OffsetDateTime offsetDateTime5 = offsetDateTime.plusDays(3);System.out.println(offsetDateTime5);//输出结果:2023-12-01T09:46:56+08:00OffsetDateTime offsetDateTime6 = offsetDateTime.plusHours(1);System.out.println(offsetDateTime6);//输出结果:2023-11-28T10:46:56+08:00OffsetDateTime offsetDateTime7 = offsetDateTime.plusMinutes(4);System.out.println(offsetDateTime7);//输出结果:2023-11-28T09:50:56+08:00OffsetDateTime offsetDateTime9 = offsetDateTime.plusSeconds(4);System.out.println(offsetDateTime9);//输出结果:2023-11-28T09:47+08:00OffsetDateTime offsetDateTime8 = offsetDateTime.plusWeeks(1);System.out.println(offsetDateTime8);//输出结果:2023-12-05T09:46:56+08:00
}

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

这些方法用于在日期时间对象中减去指定的时间单位。具体如下:

  • OffsetDateTime#minus():此方法用于在解析的日期和时间中减去指定的时间长度。它接受一个时间单位作为参数,可以是秒、分钟、小时、天等,并返回一个新的 OffsetDateTime 对象,该对象表示减去指定时间长度后的日期和时间。
  • OffsetDateTime#minusYears():此方法用于在解析的日期中减去指定的年份。它接受一个整数参数,表示要减去的年份数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定年数后的日期和时间。
  • OffsetDateTime#minusMonths():此方法用于在解析的日期中减去指定的月份。它接受一个整数参数,表示要减去的月份数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定月数后的日期和时间。
  • OffsetDateTime#minusWeeks():此方法用于在解析的日期中减去指定的周数。它接受一个整数参数,表示要减去的周数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定周数后的日期和时间。
  • OffsetDateTime#minusDays():此方法用于在解析的日期中减去指定的天数。它接受一个整数参数,表示要减去的天数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定天数后的日期和时间。
  • OffsetDateTime#minusHours():此方法用于在解析的时间中减去指定的小时数。它接受一个整数参数,表示要减去的小时数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定小时数后的日期和时间。
  • OffsetDateTime#minusMinutes():此方法用于在解析的时间中减去指定的分钟数。它接受一个整数参数,表示要减去的分钟数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定分钟数后的日期和时间。
  • OffsetDateTime#minusSeconds():此方法用于在解析的时间中减去指定的秒数。它接受一个整数参数,表示要减去的秒数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定秒数后的日期和时间。
  • OffsetDateTime#minusNanos():此方法用于在解析的时间中减去指定的纳秒数。它接受一个整数参数,表示要减去的纳秒数。返回一个新的 OffsetDateTime 对象,该对象表示减去指定纳秒数后的日期和时间。

这些方法都返回一个新生成的 OffsetDateTime 对象,而不是修改原始对象。使用这些方法可以进行精确的日期和时间计算,适用于各种场景,如日程安排、时间间隔计算等。需要注意的是,当减去负值时,将会增加相应的时间单位。例如,调用 minusYears(-1) 将增加一年。

@Test
public void test12() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));OffsetDateTime offsetDateTime1 = offsetDateTime.minus(1, ChronoUnit.YEARS);System.out.println(offsetDateTime1);//输出结果:2022-11-28T09:46:56+08:00OffsetDateTime offsetDateTime2 = offsetDateTime.minus(Period.ofYears(2));System.out.println(offsetDateTime2);//输出结果:2021-11-28T09:46:56+08:00OffsetDateTime offsetDateTime3 = offsetDateTime.minusYears(2);System.out.println(offsetDateTime3);//输出结果:2021-11-28T09:46:56+08:00OffsetDateTime offsetDateTime4 = offsetDateTime.minusMonths(1);System.out.println(offsetDateTime4);//输出结果:2023-10-28T09:46:56+08:00OffsetDateTime offsetDateTime5 = offsetDateTime.minusDays(3);System.out.println(offsetDateTime5);//输出结果:2023-11-25T09:46:56+08:00OffsetDateTime offsetDateTime6 = offsetDateTime.minusHours(1);System.out.println(offsetDateTime6);//输出结果:2023-11-28T08:46:56+08:00OffsetDateTime offsetDateTime7 = offsetDateTime.minusMinutes(4);System.out.println(offsetDateTime7);//输出结果:2023-11-28T09:42:56+08:00OffsetDateTime offsetDateTime9 = offsetDateTime.minusSeconds(4);System.out.println(offsetDateTime9);//输出结果:2023-11-28T09:46:52+08:00OffsetDateTime offsetDateTime8 = offsetDateTime.minusWeeks(1);System.out.println(offsetDateTime8);//输出结果:2023-11-21T09:46:56+08:00
}

OffsetDateTime#query(...)

OffsetDateTime#query() 接受一个TemporalQuery对象作为参数,并使用该查询对象对当前 OffsetDateTime 实例进行查询。TemporalQuery 是一个函数式接口,它接受一个 Temporal 对象并返回一个查询结果。你可以使用 OffsetDateTime#query() 方法进行各种自定义查询。

@Test
public void test13() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));TemporalQuery<Integer> temporalQuery = item -> item.get(ChronoField.YEAR);Integer year = offsetDateTime.query(temporalQuery);System.out.println(year);//输出结果:2023
}

OffsetDateTime#until(...)

OffsetDateTime#until()用于计算当前OffsetDateTime对象,以指定的单位到另一个日期时间为止的时间量。

@Test
public void test14() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2020, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));OffsetDateTime offsetDateTime2 = OffsetDateTime.of(2023, 12, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));long until = offsetDateTime.until(offsetDateTime2, ChronoUnit.MONTHS);System.out.println(until);//输出结果:37
}

OffsetDateTime#format(...)

OffsetDateTime#format() 用于将当前的日期时间对象格式化为指定的字符串表示形式。

@Test
public void test15() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2020, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));String format = offsetDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));System.out.println(format);//输出结果:2020-11-28 09:46:56
}

OffsetDateTime#atZoneSameInstant(...)、OffsetDateTime#atZoneSimilarLocal(...)

  • OffsetDateTime#atZoneSameInstant(ZoneId zone)方法的功能作用是:将此日期时间与时区组合以创建ZonedDateTime,以保持相同的本地日期和时间。该方法接受一个ZoneId类型的参数,该参数表示要使用的时区。使用该方法可以保持相同的本地日期和时间,而不会受到时区的影响。
  • OffsetDateTime#atZoneSimilarLocal(ZoneId zone)方法的功能作用是:将此日期时间与时区组合以创建ZonedDateTime,以保持相同的本地日期和时间。该方法同样接受一个ZoneId类型的参数,表示要使用的时区。使用该方法可以保持相同的本地日期和时间,但会受到时区的影响。

这两个方法的使用场景如下:

  • 在处理涉及日期时间和时区的计算或比较时,可以使用atZoneSameInstant()方法来确保在相同的本地时间点进行操作,避免时区转换带来的问题。例如,在计算两个事件之间的时间差或者比较不同时区的本地时间点时,可以使用该方法来保证计算或比较的准确性。
  • 在需要进行时区转换或处理不同时区的日期时间需求时,可以使用atZoneSimilarLocal()方法来保持相同的本地日期和时间。例如,在将一个日期时间对象从一个时区转换为另一个时区时,可以使用该方法来保持转换前后相同的本地日期和时间。

需要注意的是,这两个方法都会创建一个新的ZonedDateTime对象,而不会修改原始的OffsetDateTime对象。因此,在使用这些方法时需要注意对新的ZonedDateTime对象的处理。

@Test
public void test16() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2020, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));ZonedDateTime zonedDateTime = offsetDateTime.atZoneSimilarLocal(ZoneOffset.ofHours(-13));System.out.println(zonedDateTime);//输出结果:2020-11-28T09:46:56-13:00ZonedDateTime zonedDateTime1 = offsetDateTime.atZoneSameInstant(ZoneOffset.ofHours(-13));System.out.println(zonedDateTime1);//输出结果:2020-11-27T12:46:56-13:00
}

OffsetDateTime#toOffsetTime(...)、OffsetDateTime#toZonedDateTime(...)、OffsetDateTime#toInstant(...)、OffsetDateTime#toEpochSecond(...)

  • OffsetDateTime#toOffsetTime()的功能作用是将给定的日期时间转换为一个OffsetTime对象,这个转换将保留原始日期时间中的本地时间和偏移量。使用场景:当你需要将一个OffsetDateTime对象转换为一个OffsetTime对象,以便进行更细粒度的时间操作时,可以使用该方法。例如,如果你需要在一个应用程序中处理具体到小时的时间,但你的数据源提供的是OffsetDateTime对象,那么你可以使用toOffsetTime()方法来获取对应的OffsetTime对象。
  • OffsetDateTime#toZonedDateTime()的功能作用是将给定的OffsetDateTime对象转换为一个ZonedDateTime对象,这个转换将保留原始OffsetDateTime对象中的日期时间信息和时区信息。使用场景:当你需要将一个OffsetDateTime对象转换为一个ZonedDateTime对象,以便进行更复杂的时间和时区相关的操作时,可以使用该方法。例如,如果你需要在一个应用程序中处理涉及时区的日期时间操作,但你的数据源提供的是OffsetDateTime对象,那么你可以使用toZonedDateTime()方法来获取对应的ZonedDateTime对象。
  • OffsetDateTime#toInstant()的功能作用是将给定的OffsetDateTime对象转换为一个Instant对象,这个转换将保留原始OffsetDateTime对象中的日期时间信息和偏移量信息。使用场景:当你需要将一个OffsetDateTime对象转换为一个Instant对象,以便进行更复杂的日期时间操作,特别是涉及到跨时区的操作时,可以使用该方法。例如,如果你需要在一个应用程序中处理全球范围内的日期时间操作,但你的数据源提供的是OffsetDateTime对象,那么你可以使用toInstant()方法来获取对应的Instant对象。
  • OffsetDateTime#toEpochSecond()的功能作用是将给定的OffsetDateTime对象转换为一个long类型的Epoch秒数,这个转换将保留原始OffsetDateTime对象中的日期时间信息和偏移量信息。使用场景:当你需要将一个OffsetDateTime对象转换为一个Epoch秒数,以便进行更简单的日期时间比较或排序等操作时,可以使用该方法。例如,如果你需要在一个应用程序中对一组日期时间进行排序,但你的数据源提供的是OffsetDateTime对象,那么你可以使用toEpochSecond()方法来获取对应的Epoch秒数,并使用这些秒数进行排序。
@Test
public void test17() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2020, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));OffsetTime offsetTime = offsetDateTime.toOffsetTime();System.out.println(offsetTime);//输出结果:09:46:56+08:00ZonedDateTime zonedDateTime = offsetDateTime.toZonedDateTime();System.out.println(zonedDateTime);//输出结果:2020-11-28T09:46:56+08:00Instant instant = offsetDateTime.toInstant();System.out.println(instant);//输出结果:2020-11-28T01:46:56Zlong epochSecond = offsetDateTime.toEpochSecond();System.out.println(epochSecond);//输出结果:1606528016
}

OffsetDateTime#compareTo(...)、OffsetDateTime#isAfter(...)、OffsetDateTime#isBefore(...)、OffsetDateTime#isEqual(...)

  • OffsetDateTime#compareTo()的功能作用是比较两个OffsetDateTime对象的大小。该方法将返回一个int类型的值,其中-1表示第一个对象小于第二个对象,0表示两个对象相等,1表示第一个对象大于第二个对象。使用场景:当你需要比较两个日期时间对象的大小,以便进行排序或比较等操作时,可以使用该方法。例如,如果你有一个包含OffsetDateTime对象的列表,你需要按照日期时间顺序对列表进行排序,那么你可以使用compareTo()方法来比较每个对象的大小。
  • OffsetDateTime#isAfter()的功能作用是检查一个OffsetDateTime对象是否在另一个指定日期时间之后。如果是,则返回true;否则返回false。使用场景:当你需要确定一个日期时间是否在另一个日期时间之后时,可以使用该方法。例如,如果你有一个当前日期时间和一个结束日期时间,你需要检查当前日期时间是否晚于结束日期时间,那么你可以使用isAfter()方法进行检查。
  • OffsetDateTime#isBefore()的功能作用是检查一个OffsetDateTime对象是否在另一个指定日期时间之前。如果是,则返回true;否则返回false。使用场景:当你需要确定一个日期时间是否在另一个日期时间之前时,可以使用该方法。例如,如果你有一个开始日期时间和一个当前日期时间,你需要检查当前日期时间是否早于开始日期时间,那么你可以使用isBefore()方法进行检查。
  • OffsetDateTime#isEqual()的功能作用是检查两个OffsetDateTime对象是否相等。如果是,则返回true;否则返回false。使用场景:当你需要比较两个日期时间对象是否相等时,可以使用该方法。例如,如果你有两个日期时间对象需要比较是否相同,那么你可以使用isEqual()方法进行检查。
@Test
public void test18() {OffsetDateTime offsetDateTime = OffsetDateTime.of(2020, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(8));OffsetDateTime offsetDateTime2 = OffsetDateTime.of(2020, 11, 28, 9, 46, 56, 0, ZoneOffset.ofHours(-5));int compareTo = offsetDateTime.compareTo(offsetDateTime2);System.out.println(compareTo);//输出结果:-1boolean before = offsetDateTime.isBefore(offsetDateTime2);System.out.println(before);//输出结果:trueboolean after = offsetDateTime.isAfter(offsetDateTime2);System.out.println(after);//输出结果:falseboolean equal = offsetDateTime.isEqual(offsetDateTime2);System.out.println(equal);//输出结果:false
}

OffsetDateTime的使用场景

OffsetDateTime的使用场景非常广泛,主要包括以下几个方面:

  • 日期时间操作:OffsetDateTime可以用于表示和操作具体的日期和时间,包括年、月、日、小时、分钟、秒等。可以用于计算时间差、比较日期时间的大小、进行日期时间的格式化等。
  • 时区处理:在处理全球化的日期时间时,OffsetDateTime可以表示不同的时区。通过存储偏移量信息,可以方便地在不同时区之间转换日期时间。
  • 日历和日程安排:OffsetDateTime可以用于日历系统的开发,例如制作日程表、安排会议等。可以方便地获取某个特定日期或时间的信息,以及进行日期的计算和时间间隔的测量。
  • 金融和商务应用:在金融和商务领域,OffsetDateTime可以用于处理交易时间、计算利息、处理时间差异等问题。可以确保交易的准确性和一致性,避免因时区差异带来的问题。
  • 系统管理和监控:在系统管理和监控方面,OffsetDateTime可以用于记录系统事件、生成日志、跟踪任务执行时间等。可以方便地获取事件发生的具体时间和日期,以及进行相关的时间计算和分析。
  • 时间和日期的展示:在需要展示日期时间和时区的应用场景下,例如网站或应用程序的用户界面,OffsetDateTime可以用于获取当前日期时间和时区信息,以及进行日期时间的格式化展示。

总之,OffsetDateTime在各种应用场景下都可以发挥重要作用,特别是在需要处理全球化日期时间、时区转换、精确时间戳等需求的场景下。

相关文章:

  • RocketMQ-快速实战
  • docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbor
  • 【开源】基于JAVA的大病保险管理系统
  • matlab 混沌动力学行为-分岔图-李雅普指数等
  • 推荐几款python在线学习和电子书网站
  • 带你手搓阻塞队列——自定义实现
  • 【UGUI】Unity教程:实现物品的拖拽功能
  • SpringBoot+mysql+vue实现大学生健康档案管理系统前后端分离
  • MySQL数据库的备份与恢复
  • 腾讯云手动下发指令到设备-用于设备调试
  • 全栈冲刺 之 一天速成MySQL
  • 知乎禁止转载的回答怎么复制做笔记?
  • 恒驰服务 | 华为云云上运维服务offering
  • 近期知识点随笔
  • 【Java】使用IntelliJ IDEA搭建SSM(MyBatis-Plus)框架并连接MySQL数据库
  • [数据结构]链表的实现在PHP中
  • 【个人向】《HTTP图解》阅后小结
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • JavaWeb(学习笔记二)
  • Java到底能干嘛?
  • Java深入 - 深入理解Java集合
  • JS+CSS实现数字滚动
  • Koa2 之文件上传下载
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • MySQL的数据类型
  • nodejs:开发并发布一个nodejs包
  • nodejs调试方法
  • React-flux杂记
  • VuePress 静态网站生成
  • vue数据传递--我有特殊的实现技巧
  • vue总结
  • webpack项目中使用grunt监听文件变动自动打包编译
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 初探 Vue 生命周期和钩子函数
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 开源地图数据可视化库——mapnik
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • Spring Batch JSON 支持
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (04)odoo视图操作
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (六)软件测试分工
  • (三)uboot源码分析
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • **CI中自动类加载的用法总结
  • .chm格式文件如何阅读
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET 的静态构造函数是否线程安全?答案是肯定的!