深入了解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在各种应用场景下都可以发挥重要作用,特别是在需要处理全球化日期时间、时区转换、精确时间戳等需求的场景下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/226409.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【axios封装】万字长文,TypeScript实战,封装一个axios - 基础封装篇

目录 前言版本环境变量配置引入的类型1、AxiosIntance: axios实例类型2、InternalAxiosRequestConfig: 高版本下AxiosRequestConfig的拓展类型3、AxiosRequestConfig: 请求体配置参数类型4、AxiosError: 错误对象类型5、AxiosResponse: 完整原始响应体类型 目标效果开始封装骨架…

解读 | 从谷歌AI判定阿波罗登月“造假“来谈谈合成图片检测技术

大家好&#xff0c;我是极智视界&#xff0c;欢迎关注我的公众号&#xff0c;获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码和资源下载&#xff0c;链接&#xff1a;https://t.zsxq.com/0aiNxERDq 整个事情可以爬楼看…

【数据库】基于排序算法的去重,集合与包的并,差,交,连接操作实现原理,执行代价以及优化

基于两趟排序的其它操作 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏…

数据结构代码更新中...

代码上传至gitee中&#xff0c;点击此处查看。 下面是思路的阐述 动态数组的实现 dynamicArray.h #pragma once#include <iostream> #include <string> #include <stdlib.h> using namespace std;typedef struct dynamicArray {void** pAddr;int capacit…

强化学习中的Q学习

Q学习&#xff08;Q-Learning&#xff09;是强化学习中的一种基于值的学习方法&#xff0c;用于在有限马尔可夫决策过程&#xff08;MDP&#xff09;中学习最优的动作策略。Q学习主要用于离散状态和离散动作的问题。 以下是Q学习的基本概念和步骤&#xff1a; Q-Value&#xf…

Python分享之字符串格式化 (%操作符)

在许多编程语言中都包含有格式化字符串的功能&#xff0c;比如C和Fortran语言中的格式化输入输出。Python中内置有对字符串进行格式化的操作%。 模板 格式化字符串时&#xff0c;Python使用一个字符串作为模板。模板中有格式符&#xff0c;这些格式符为真实值预留位置&#xff…

Redis 事件轮询

1 Redis 为什么快 数据存在内存中, 直接操作内存中的数据单线程处理业务请求避免了多线的上下文切换, 锁竞争等弊端使用 IO 多路复用支撑更高的网络请求使用事件驱动模型, 通过事件通知模式, 减少不必要的等待… 这些都是 Redis 快的原因。 但是这些到了代码层面是如何实现的呢…

【C++ Primer Plus学习记录】do while循环

do while循环是出口条件循环。这意味着这种循环将首先执行循环体&#xff0c;然后再判定测试表达式&#xff0c;决定是否应继续执行循环。如果条件为false&#xff0c;则循环终止&#xff1b;否则&#xff0c;进入新一轮的执行和测试。这样的循环通常至少执行一次&#xff0c;因…

sed命令

目录 一、sed 1.sed命令选项 2.语法选项 3.sed脚本格式 4.搜索替代 5.分组后向引用 1.提取版本号&#xff1a; 2.提取IP地址 3.提取数字权限 6.变量 二、免交互 1.多行重定向 2.免交互脚本 总结&#xff1a;本章主要介绍了seq和免交互的用法及相关知识 一、sed s…

通过网易的API完成一个简易的音乐播放器

效果图 工程环境 1、使用node在本地部署网易云音乐API接口 下载解压 链接:https://pan.baidu.com/s/1YQiMJoUMEYlMz14FH5xxRA?pwd36o5 提取码:36o5 工程目录概览 &#xff08;js文件夹里面放了music.html和main.js和vue.js&#xff09; 工程目录)&#xff08;有点重复…

Boot工程快速启动【Linux】

Boot工程快速启动【Linux】 在idea中打包cd usr/在local文件夹下mkdir app进入app文件夹把打包好的文件&#xff08;只上传其中的jar&#xff09;上传到app文件下检查linux中的Java版本&#xff0c;保证和项目的Java 版本保持一致运行 java -jar sp补全***.jar想看效果得查询当…

MySQL进阶-InnoDB引擎

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、语雀 、Github &#x1f389;公众号&#xff1a;猫十二懿 一、InnoDB 逻辑存储引擎 InnoDB的逻辑存储结构如下图所示&#xff1a; 大小关系&#xff1a;表空间&#xff08;Tablespace&#xff0…