深入了解Java8新特性-日期时间API:LocalDateTime类
阅读建议
嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:
- 本篇文章大概22000多字,预计阅读时间长需要20分钟以上。
- 本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章,建议收藏起来,方便时常学习与回顾,温故而知新。
- 创作不易,免费的点赞、关注,请走上一走,算是对博主一些鼓励,让我更有动力输出更多的干货内容。
注意
本文编写的单元测试是基于java11,具体的版本号是:11.0.19
关于LocalDateTime
LocalDateTime 是 Java 8 中引入的一个新的日期时间 API,它表示一个没有时区的日期时间对象,是不可变且线程安全的。LocalDateTime 通常用于需要同时表示日期和时间,但不涉及时区的场景。
LocalDateTime、LocalDate和LocalTime都是Java中用于表示日期和时间的数据类型,但它们在功能和使用上有一些重要的区别。
与LocalDate的区别
功能:
- LocalDateTime:是一个不可变的日期时间对象,包含日期和时间信息,通常被视为年-月-日-时-分-秒。它也可以访问其他日期和时间字段,例如一年中的某天、一周中的某天和一周中的某周。时间以纳秒精度表示。LocalDateTime是不可变的,提供了各种方法来操作和提取日期和时间值,并且是线程安全的。
- LocalDate:也是一个不可变的日期时间对象,但只包含日期信息,通常被视为年-月-日。它不包含时间信息。LocalDate提供了方法来操作和提取日期值,但不包括时间信息。同样,它是不可变的,并且是线程安全的。
使用场景:
- 如果需要同时处理日期和时间信息,LocalDateTime更为适用。
- 如果只需要操作日期,不需要时间信息,LocalDate可能更合适。
与LocalTime的区别
功能:
- LocalDateTime表示日期和时间,不包含时区信息。它是一个不可变类,提供了一系列方法来获取、设置和操作年、月、日、时、分、秒等日期和时间的不同部分,以及进行比较、格式化、解析等操作。LocalDateTime是LocalDate和LocalTime的组合,可以用于存储和操作具体的日期和时间。
- LocalTime表示时间,不包含日期和时区信息。它也是不可变类,提供了一系列方法来获取、设置和操作时、分、秒等时间的不同部分,以及进行比较、格式化等操作。LocalTime可以用于存储和操作每天的固定时间点,如午夜、中午等。
使用场景
- 如果需要同时处理日期和时间信息,LocalDateTime更为适用。
- 如果只需要操作时间,不需要日期信息,LocalTime可能更合适。
核心方法
LocalDateTime#now()
LocalDateTime#now() 用于获取当前的日期和时间,不包含时区信息。
@Test
public void test() {
LocalDateTime now = LocalDateTime.now();
String format = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(format);//当前日期和时间:2023-11-27 11:23:54
}
LocalDateTime#of(...)、LocalDateTime#ofInstant(...)、LocalDateTime#ofEpochSecond(...)
- LocalDateTime#of():这个方法用于创建一个具有特定日期和时间的LocalDateTime对象。它接受年、月、日、时、分、秒作为参数,返回一个对应的LocalDateTime实例。使用场景包括需要创建一个特定的日期和时间对象,例如生日、纪念日等。
- LocalDateTime#ofInstant():这个方法用于使用Instant和时区ID创建LocalDateTime的实例。它将两个参数传递给方法,一个是Instant类型,表示传递给创建localdatetime的瞬间,另一个是ZoneId类型,代表用于创建偏移量的时区。该方法返回一个对应的LocalDateTime实例。使用场景包括需要将一个瞬时转化为本地日期和时间,例如在处理与时间相关的数据时,需要将UTC时间转换为本地时间。
- LocalDateTime#ofEpochSecond():这个方法用于根据秒数和纳秒数创建一个LocalDateTime对象。它接受秒数和纳秒数作为参数,返回一个对应的LocalDateTime实例。使用场景包括需要将秒数和纳秒数转化为日期和时间对象,例如在处理时间戳等数据时,需要将秒数和纳秒数转换为日期和时间对象。
@Test
public void test2() {
LocalDateTime localDateTime = LocalDateTime.of(2023, 11, 27, 11, 27, 56);
System.out.println(localDateTime);//输出结果:2023-11-27T11:27:56
LocalDate localDate = LocalDate.of(2023, 11, 27);
LocalTime localTime = LocalTime.of(11, 27, 56);
LocalDateTime localDateTime1 = LocalDateTime.of(localDate, localTime);
System.out.println(localDateTime1);//输出结果:2023-11-27T11:27:56
LocalDateTime localDateTime2 = LocalDateTime.ofInstant(Instant.ofEpochSecond(61), ZoneId.systemDefault());
System.out.println(localDateTime2);//输出结果:1970-01-01T08:01:01
LocalDateTime localDateTime3 = LocalDateTime.ofEpochSecond(61, 0, ZoneOffset.ofHours(8));
System.out.println(localDateTime3);//输出结果:1970-01-01T08:01:01
}
LocalDateTime#from(...)
LocalDateTime#from(...)用于从给定的日期时间对象中创建一个新的LocalDateTime实例。这个方法接受一个Object类型的参数,这个对象需要是以下类型之一:
- ZonedDateTime
- OffsetDateTime
- Instant
- LocalDate
- LocalTime
- YearMonth
- MonthDay
- YearWeek
- Year
- Month
- DayOfWeek
- WeekOfMonth
- WeekOfYear
- DayOfYear
- MonthDayOfYear
- YearMonthDayOfYear
当给定的日期时间对象为以上所列出的类型之一时,LocalDateTime#from(...)方法会尝试从中提取日期和时间信息,并创建一个新的LocalDateTime实例。如果给定的对象无法转换为LocalDateTime,那么这个方法会抛出一个DateTimeException异常。
这个方法的使用场景通常是在需要将一个日期时间对象转换为LocalDateTime,以便进行后续的日期和时间运算或处理。例如,你可能从数据库中获取了一个日期时间戳,然后你需要将这个日期时间戳转换为LocalDateTime,以便进行进一步的计算或处理。或者,你可能需要从一个具有特定时区的日期时间对象中创建一个没有时区的LocalDateTime。
@Test
public void test3() {
LocalDateTime localDateTime = LocalDateTime.parse("2023-11-2711:36:56", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalDateTime from = LocalDateTime.from(localDateTime);
System.out.println(from);//输出结果:2023-11-2711:36:56
}
LocalDateTime#parse(...)
LocalDateTime#parse(...) 用于将字符串解析为 LocalDateTime 对象的函数。该方法使用一个字符串作为输入,并根据该字符串的内容创建一个新的 LocalDateTime 对象。
在使用该方法时,该字符串必须符合 ISO 8601 格式,例如 "2019-01-01T12:00:00",另外还需要注意时区的问题。如果字符串中没有指定时区信息,那么解析出来的 LocalDateTime 对象将是本地时区的时间。如果需要指定时区,可以使用 ZoneId 类的 of 方法来创建时区对象,然后使用 LocalDateTime.atZone 方法将 LocalDateTime 对象转换为 ZonedDateTime 对象,最后再使用 ZonedDateTime.toLocalDateTime 方法将其转换为指定时区的 LocalDateTime 对象。
@Test
public void test4() {
LocalDateTime localDateTime = LocalDateTime.parse("2023-11-2711:36:56", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(localDateTime);//输出结果:2023-11-2711:36:56
}
LocalDateTime#isSupported(...)
LocalDateTime#isSupported() 用于检查是否支持特定的单位或字段。该方法接受一个参数,可以是 TemporalUnit 或 TemporalField 对象,用于指定要检查的单位或字段。如果支持,方法将返回 true;如果不支持,方法将返回 false。
使用场景:
- 需要对日期时间进行特定单位或字段的操作时:如果需要在代码中使用 LocalDateTime 对象进行日期时间操作,并需要确保所使用的字段或单位是受支持的,可以使用 LocalDateTime#isSupported() 方法进行检查。例如,在执行加减运算之前,可以使用该方法检查是否支持特定的时间单位。
- 需要进行日期时间格式验证时:在使用 LocalDateTime 对象处理日期时间数据时,可能需要对输入数据进行格式验证。通过调用 LocalDateTime#isSupported() 方法并传递相应的单位或字段参数,可以验证输入数据是否符合要求。例如,可以检查日期时间字符串是否包含不合法的字段或单位。
@Test
public void test5() {
LocalDateTime now = LocalDateTime.now();
boolean supported = now.isSupported(ChronoUnit.YEARS);
boolean supported1 = now.isSupported(ChronoField.DAY_OF_YEAR);
System.out.println(supported);//输出结果:true
System.out.println(supported1);//输出结果:true
}
LocalDateTime#range(...)
LocalDateTime#range(...) 用于获取LocalDateTime对象指定字段的有效值范围,返回值是一个ValueRange对象,range对象表示字段的最小和最大有效值。此日期时间用于提高返回范围的准确性。如果由于不支持该字段或其他原因而无法返回范围,则会引发异常。
@Test
public void test6() {
LocalDateTime now = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
ValueRange range = now.range(ChronoField.DAY_OF_MONTH);
long maximum = range.getMaximum();
long minimum = range.getMinimum();
System.out.println(maximum);//输出结果:29
System.out.println(minimum);//输出结果:1
LocalDateTime now2 = LocalDateTime.of(2023, 2, 1, 12, 18, 56);
ValueRange range2 = now2.range(ChronoField.DAY_OF_MONTH);
long maximum2 = range2.getMaximum();
long minimum2 = range2.getMinimum();
System.out.println(maximum2);//输出结果:28
System.out.println(minimum2);//输出结果:1
}
LocalDateTime#get(...)、LocalDateTime#getLong(...)、LocalDateTime#getYear(...)、LocalDateTime#getMonthValue(...)、LocalDateTime#getMonth(...)、LocalDateTime#getDayOfMonth(...)、LocalDateTime#getDayOfYear(...)、LocalDateTime#getDayOfWeek(...)、LocalDateTime#getHour(...)、LocalDateTime#getMinute(...)、LocalDateTime#getSecond(...)、LocalDateTime#getNano(...)
- LocalDateTime#get(TemporalField):此方法获取给定时间字段的值。参数可以是年、月、日、时、分、秒或纳秒等。它通常用于对日期和时间进行精细操作或计算。
- LocalDateTime#getLong(TemporalField):此方法获取给定时间字段的长整型值。它的使用场景与get方法类似,但返回值是长整型的。
- LocalDateTime#getYear():此方法返回当前日期的年份。它通常用于进行年份相关的计算或处理。
- LocalDateTime#getMonthValue():此方法返回当前月份的值,以整数形式表示。它通常用于处理或操作月份信息。
- LocalDateTime#getMonth():此方法返回当前月份的Text,如"January"、"February"等。它主要用于获取月份的全称。
- LocalDateTime#getDayOfMonth():此方法返回当前日期的日,以整数形式表示。它通常用于处理或操作具体的日期信息。
- LocalDateTime#getDayOfYear():此方法返回当前日期是一年中的第几天,以整数形式表示。它主要用于计算或处理一年中的日期信息。
- LocalDateTime#getDayOfWeek():此方法返回当前日期是星期几,以Text形式表示,如"Monday"、"Tuesday"等。它主要用于获取星期的全称。
- LocalDateTime#getHour():此方法返回当前时间的时,以整数形式表示。它通常用于处理或操作具体的小时信息。
- LocalDateTime#getMinute():此方法返回当前时间的分,以整数形式表示。它通常用于处理或操作具体的分钟信息。
- LocalDateTime#getSecond():此方法返回当前时间的秒,以整数形式表示。它通常用于处理或操作具体的秒信息。
- LocalDateTime#getNano():此方法返回当前时间的纳秒,以整数形式表示。它主要用于获取纳秒级别的精度信息。
@Test
public void test7() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
int year = localDateTime.get(ChronoField.YEAR);
System.out.println(year);//输出结果:2020
int month = localDateTime.get(ChronoField.MONTH_OF_YEAR);
System.out.println(month);//输出结果:2
long yearLong = localDateTime.getLong(ChronoField.YEAR);
System.out.println(yearLong);//输出结果:2020
long monthLong = localDateTime.getLong(ChronoField.MONTH_OF_YEAR);
System.out.println(monthLong);//输出结果:2
int year1 = localDateTime.getYear();
System.out.println(year1);//输出结果:2020
int monthValue = localDateTime.getMonthValue();
System.out.println(monthValue);//输出结果:2
int dayOfMonth = localDateTime.getDayOfMonth();
System.out.println(dayOfMonth);//输出结果:1
int dayOfYear = localDateTime.getDayOfYear();
System.out.println(dayOfYear);//输出结果:32
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
int dayOfWeekValue = dayOfWeek.getValue();
System.out.println(dayOfWeekValue);//输出结果:6
int hour = localDateTime.getHour();
System.out.println(hour);//输出结果:12
int minute = localDateTime.getMinute();
System.out.println(minute);//输出结果:18
int second = localDateTime.getSecond();
System.out.println(second);//输出结果:56
}
LocalDateTime#toLocalDate(...)、LocalDateTime#toLocalTime(...)
- toLocalDate() 方法:该方法用于从 LocalDateTime 对象中获取 LocalDate 对象。它返回一个 LocalDate 实例,表示此 LocalDateTime 对象的日期部分。
- toLocalTime() 方法:该方法用于从 LocalDateTime 对象中获取 LocalTime 对象。它返回一个 LocalTime 实例,表示此 LocalDateTime 对象的时间部分。
@Test
public void test8() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();
System.out.println(localDate);//输出结果:2020-02-01
System.out.println(localTime);//输出结果:12:18:56
}
LocalDateTime#with(...)、LocalDateTime#withYear(...)、LocalDateTime#withMonth(...)、LocalDateTime#withDayOfMonth(...)、LocalDateTime#withDayOfYear(...)、LocalDateTime#withHour(...)、LocalDateTime#withMinute(...)、LocalDateTime#withSecond(...)、LocalDateTime#withNano(...)
上述这些方法可以在不改变日期和时间的其他部分的情况下,对日期和时间的特定部分进行修改和操作。具体来说:
- LocalDateTime#with():该方法用于使用 TemporalAdjuster 调整此日期时间,并在调整后返回调整后的日期时间的副本。使用指定的调整器策略对象进行调整。
- LocalDateTime#withYear():该方法用于获取此 LocalDateTime 的副本,并将年份更改为作为该方法的参数传递的年份。此 LocalDateTime 的其余值保持不变。年份的值范围可以从 MIN_YEAR 到 MAX_YEAR。
- LocalDateTime#withMonth():该方法用于获取此 LocalDateTime 的副本,并将月份更改为作为该方法的参数传递的月份。此 LocalDateTime 的其余值保持不变。月份的值范围从 1 到 12。
- LocalDateTime#withDayOfMonth():该方法用于获取此 LocalDateTime 的副本,并将日更改为作为该方法的参数传递的日。此 LocalDateTime 的其余值保持不变。日的值范围从 1 到月份的天数。
- LocalDateTime#withDayOfYear():该方法用于获取此 LocalDateTime 的副本,并将一年中的日子更改为作为该方法的参数传递的日子。此 LocalDateTime 的其余值保持不变。天的值范围从 1 到 365 或 366(取决于年份是否为闰年)。
- LocalDateTime#withHour():该方法用于获取此 LocalDateTime 的副本,并将小时更改为作为该方法的参数传递的小时。此 LocalDateTime 的其余值保持不变。小时的值范围从 0 到 23。
- LocalDateTime#withMinute():该方法用于获取此 LocalDateTime 的副本,并将分钟更改为作为该方法的参数传递的分钟。此 LocalDateTime 的其余值保持不变。分钟的值的范围从 0 到 59。
- LocalDateTime#withSecond():该方法用于获取此 LocalDateTime 的副本,并将秒更改为作为该方法的参数传递的秒。此 LocalDateTime 的其余值保持不变。秒的值范围从 0 到 59(或 60,如果该秒是闰秒)。
- LocalDateTime#withNano():该方法用于获取此 LocalDateTime 的副本,并将纳秒更改为作为该方法的参数传递的纳秒。此 LocalDateTime 的其余值保持不变。纳秒的值范围从 0 到 999,999,999。
@Test
public void test9() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
TemporalAdjuster temporalAdjuster = item -> item.plus(1, ChronoUnit.HOURS);
LocalDateTime localDateTime1 = localDateTime.with(temporalAdjuster);
System.out.println(localDateTime1);//输出结果:2020-02-01T13:18:56
LocalDateTime localDateTime2 = localDateTime.with(ChronoField.HOUR_OF_DAY, 1);
System.out.println(localDateTime2);//输出结果:2020-02-01T01:18:56
LocalDateTime localDateTime3 = localDateTime.withYear(2023);
System.out.println(localDateTime3);//输出结果:2023-02-01T12:18:56
LocalDateTime localDateTime4 = localDateTime.withMonth(1);
System.out.println(localDateTime4);//输出结果:2020-01-01T12:18:56
LocalDateTime localDateTime5 = localDateTime.withDayOfMonth(10);
System.out.println(localDateTime5);//输出结果:2020-02-10T12:18:56
LocalDateTime localDateTime6 = localDateTime.withHour(18);
System.out.println(localDateTime6);//输出结果:2020-02-01T18:18:56
LocalDateTime localDateTime7 = localDateTime.withMinute(30);
System.out.println(localDateTime7);//输出结果:2020-02-01T12:30:56
LocalDateTime localDateTime8 = localDateTime.withSecond(59);
System.out.println(localDateTime8);//输出结果:2020-02-01T12:18:59
}
LocalDateTime#truncatedTo(...)
LocalDateTime#truncatedTo()用于将当前LocalDateTime对象的时间部分截断到给定的时间单位。
功能作用:
- 截断日期时间:通过调用LocalDateTime#truncatedTo()方法,可以将当前LocalDateTime对象的时间部分截断到给定的时间单位,例如分钟、小时、天等。截断后的LocalDateTime对象将不再包含被截断单位之前的时间信息。
- 提供灵活的时间操作:使用LocalDateTime#truncatedTo()方法可以根据具体需求将日期时间截断到不同的时间单位,从而实现灵活的时间操作。例如,可以将日期时间截断到分钟级别,然后进行加减运算,以实现精确到分钟的日期时间计算。
使用场景:
- 需要截断日期时间时:在一些特定的应用场景中,可能需要对日期时间进行截断操作。例如,在进行统计或数据分析时,可能只需要日期时间中的某一部分信息,而不需要保留完整的时间信息。在这种情况下,可以使用LocalDateTime#truncatedTo()方法将日期时间截断到所需的时间单位。
- 需要进行时间运算时:在进行时间运算时,如计算两个日期时间之间的差值或进行日期的加减运算等,可以将日期时间截断到分钟或小时级别,以避免因毫秒级的时间差异而产生误差。例如,可以使用LocalDateTime#truncatedTo()方法将日期时间截断到分钟级别,然后进行加减运算,以实现精确到分钟的日期时间计算。
@Test
public void test10() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
LocalDateTime localDateTime1 = localDateTime.truncatedTo(ChronoUnit.DAYS);
System.out.println(localDateTime1);//输出结果:2020-02-01T00:00
}
LocalDateTime#plus(...)、LocalDateTime#plusYears(...)、LocalDateTime#plusMonths(...)、LocalDateTime#plusWeeks(...)、LocalDateTime#plusDays(...)、LocalDateTime#plusHours(...)、LocalDateTime#plusMinutes(...)、LocalDateTime#plusSeconds(...)、LocalDateTime#plusNanos(...)
上述方法,主要用于在现有的日期时间对象上增加指定的时间单位或量。
具体如下:
- LocalDateTime#plus(long amount, TemporalUnit unit):增加给定数量的单位到当前的日期时间对象。参数amount表示要增加的数量,参数unit表示要增加的时间单位,例如DAYS、WEEKS、MONTHS等。
- LocalDateTime#plusYears(long years):在当前日期时间对象上增加指定的年份数。参数years表示要增加的年份数,可以为负数。
- LocalDateTime#plusMonths(long months):在当前日期时间对象上增加指定的月份数。参数months表示要增加的月份数,可以为负数。
- LocalDateTime#plusWeeks(long weeks):在当前日期时间对象上增加指定的周数。参数weeks表示要增加的周数,可以为负数。
- LocalDateTime#plusDays(long days):在当前日期时间对象上增加指定的天数。参数days表示要增加的天数,可以为负数。
- LocalDateTime#plusHours(long hours):在当前日期时间对象上增加指定的小时数。参数hours表示要增加的小时数,可以为负数。
- LocalDateTime#plusMinutes(long minutes):在当前日期时间对象上增加指定的分钟数。参数minutes表示要增加的分钟数,可以为负数。
- LocalDateTime#plusSeconds(long seconds):在当前日期时间对象上增加指定的秒数。参数seconds表示要增加的秒数,可以为负数。
- LocalDateTime#plusNanos(long nanos):在当前日期时间对象上增加指定的纳秒数。参数nanos表示要增加的纳秒数,可以为负数。
使用场景:
- 日期时间的计算和运算:可以通过调用这些方法来对日期时间进行计算和运算。例如,可以使用LocalDateTime#plusYears()方法来计算未来某一年的日期时间,或者使用LocalDateTime#plusDays()方法来计算未来某一天的日期时间。
- 定时器和定时任务:这些方法可以与Java中的定时器类(如java.util.Timer)结合使用,以实现定时任务或定时触发某些操作。例如,可以使用LocalDateTime#now()方法获取当前日期时间,然后将其作为定时器的触发时间。
- 时间的调整和格式化:可以使用这些方法来对日期时间进行调整和格式化。例如,可以使用LocalDateTime#plusHours()方法来将当前时间向前移动几个小时,或者使用LocalDateTime#format()方法将日期时间格式化为特定的字符串格式。
- 日历和日程安排:这些方法可以用于日历和日程安排应用中。例如,可以使用LocalDateTime#plusMonths()方法来计算下个月的日期时间,或者使用LocalDateTime#plusWeeks()方法来计算未来一周的日期时间。
@Test
public void test11() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
LocalDateTime localDateTime1 = localDateTime.plus(Period.ofDays(3));
LocalDateTime localDateTime2 = localDateTime.plus(3, ChronoUnit.DAYS);
System.out.println(localDateTime1);//输出结果:2020-02-04T12:18:56
System.out.println(localDateTime2);//输出结果:2020-02-04T12:18:56
LocalDateTime localDateTime3 = localDateTime.plusYears(1);
System.out.println(localDateTime3);//输出结果:2021-02-01T12:18:56
LocalDateTime localDateTime4 = localDateTime.plusMonths(1);
System.out.println(localDateTime4);//输出结果:2020-03-01T12:18:56
LocalDateTime localDateTime5 = localDateTime.plusWeeks(1);
System.out.println(localDateTime5);//输出结果:2020-02-08T12:18:56
LocalDateTime localDateTime6 = localDateTime.plusDays(10);
System.out.println(localDateTime6);//输出结果:2020-02-11T12:18:56
LocalDateTime localDateTime7 = localDateTime.plusHours(3);
System.out.println(localDateTime7);//输出结果:2020-02-01T15:18:56
LocalDateTime localDateTime8 = localDateTime.plusMinutes(12);
System.out.println(localDateTime8);//输出结果:2020-02-01T12:30:56
LocalDateTime localDateTime9 = localDateTime.plusSeconds(4);
System.out.println(localDateTime9);//输出结果:2020-02-01T12:19
}
LocalDateTime#minus(...)、LocalDateTime#minusYears(...)、LocalDateTime#minusMonths(...)、LocalDateTime#minusWeeks(...)、LocalDateTime#minusDays(...)、LocalDateTime#minusHours(...)、LocalDateTime#minusMinutes(...)、LocalDateTime#minusSeconds(...)、LocalDateTime#minusNanos(...)
上述这些方法,用于对日期和时间的减法操作,需要注意的是,这些方法的计算结果值超过限制时可能会抛出DateTimeException异常。
具体如下:
- LocalDateTime#minus():该方法用于在当前LocalDateTime对象中减去指定的时间间隔。它接受一个TemporalAmount参数,表示要减去的金额。返回值是此日期时间的副本,减去指定的金额。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的时间间隔。
- LocalDateTime#minusYears():该方法用于从此日期时间对象中减去给定的年份并返回LocalDateTime。它接受一个long类型的参数,表示要减去的年份数。返回值是保存从该LocalDateTime减去给定年份的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的年份数。
- LocalDateTime#minusMonths():该方法用于从此日期时间对象中减去给定的月份并返回LocalDateTime。它接受一个long类型的参数,表示要减去的月份数。返回值是保存从该LocalDateTime减去给定月份的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的月份数。
- LocalDateTime#minusWeeks():该方法用于从此日期时间对象中减去给定的周数并返回LocalDateTime。它接受一个long类型的参数,表示要减去的周数数。返回值是保存从该LocalDateTime减去给定周数的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的周数数。
- LocalDateTime#minusDays():该方法用于从此日期时间对象中减去给定的天数并返回LocalDateTime。它接受一个long类型的参数,表示要减去的天数数。返回值是保存从该LocalDateTime减去给定天数的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的天数数。
- LocalDateTime#minusHours():该方法用于从此日期时间对象中减去给定的小时数并返回LocalDateTime。它接受一个long类型的参数,表示要减去的小时数。返回值是保存从该LocalDateTime减去给定小时数的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的小时数。
- LocalDateTime#minusMinutes():该方法用于从此日期时间对象中减去给定的分钟数并返回LocalDateTime。它接受一个long类型的参数,表示要减去的分钟数。返回值是保存从该LocalDateTime减去给定分钟数的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的分钟数。
- LocalDateTime#minusSeconds():该方法用于从此日期时间对象中减去给定的秒数并返回LocalDateTime。它接受一个long类型的参数,表示要减去的秒数。返回值是保存从该LocalDateTime减去给定秒数的值的LocalDateTime。使用场景:在进行日期时间的减法操作时,可以使用该方法来减去指定的秒数。
- LocalDateTime#minusNanos():该方法用于从此日期时间对象中减去给定的纳秒数并返回LocalDateTime。它接受一个long类型的参数,表示要减去的纳秒数。返回值是保存从该LocalDateTime减去给定纳秒数的值的LocalDateTime。使用场景:在进行高精度日期时间的减法操作时,可以使用该方法来减去指定的纳秒数。
@Test
public void test12() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
LocalDateTime localDateTime1 = localDateTime.minus(Period.ofDays(3));
LocalDateTime localDateTime2 = localDateTime.minus(3, ChronoUnit.DAYS);
System.out.println(localDateTime1);//输出结果:2020-01-29T12:18:56
System.out.println(localDateTime2);//输出结果:2020-01-29T12:18:56
LocalDateTime localDateTime3 = localDateTime.minusYears(1);
System.out.println(localDateTime3);//输出结果:2019-02-01T12:18:56
LocalDateTime localDateTime4 = localDateTime.minusMonths(1);
System.out.println(localDateTime4);//输出结果:2020-01-01T12:18:56
LocalDateTime localDateTime5 = localDateTime.minusWeeks(1);
System.out.println(localDateTime5);//2020-01-25T12:18:56
LocalDateTime localDateTime6 = localDateTime.minusDays(10);
System.out.println(localDateTime6);//输出结果:2020-01-22T12:18:56
LocalDateTime localDateTime7 = localDateTime.minusHours(3);
System.out.println(localDateTime7);//输出结果:2020-02-01T09:18:56
LocalDateTime localDateTime8 = localDateTime.minusMinutes(12);
System.out.println(localDateTime8);//输出结果:2020-02-01T12:06:56
LocalDateTime localDateTime9 = localDateTime.minusSeconds(4);
System.out.println(localDateTime9);//输出结果:2020-02-01T12:18:52
}
LocalDateTime#query(...)
LocalDateTime#query()接受一个TemporalQuery作为参数,用于查询此LocalDateTime。查询的结果会根据传递的查询逻辑来决定。通常在需要基于特定的查询逻辑处理日期和时间的情况下使用。传递给查询方法的逻辑是通过TemporalQuery对象定义的。因此,这个方法在使用时需要结合具体的查询需求和TemporalQuery的实现来使用。
@Test
public void test13() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
TemporalQuery<Integer> temporalQuery = item -> item.get(ChronoField.YEAR);
Integer year = localDateTime.query(temporalQuery);
System.out.println(year);//输出结果:2020
}
LocalDateTime#until(...)
LocalDateTime#until() 方法用于计算两个 LocalDateTime 对象之间的时间量,并以指定的 TemporalUnit 为单位返回结果。这个方法返回一个整数,表示两个 LocalDateTime 对象之间完整的时间单位数。
功能作用:
- 计算时间差:LocalDateTime#until() 方法可以计算两个 LocalDateTime 对象之间的时间差。通过调用该方法并传递一个 TemporalUnit 参数,可以获取两个日期时间之间的差距,单位可以是秒、分钟、小时、天等。
- 提供灵活的时间计算:使用 LocalDateTime#until() 方法可以根据具体需求计算不同时间单位之间的差值。这使得开发者能够根据实际需求进行精确到秒、分钟、小时或天的时间计算,以满足不同的业务需求。
使用场景:
- 需要计算时间差时:在一些特定的应用场景中,可能需要对两个日期时间之间的时间差进行计算。例如,在记录用户活动日志时,需要计算用户两次操作之间的时间差,以便对用户行为进行分析。在这种情况下,可以使用 LocalDateTime#until() 方法来获取准确的时间差值。
- 需要进行时间运算时:除了计算时间差,LocalDateTime#until() 方法还可以用于时间运算。例如,可以使用该方法计算两个日期之间的天数,然后根据计算结果进行相应的操作。这可以帮助开发者在处理日期时间时提高计算的准确性和灵活性。
@Test
public void test14() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
long until = localDateTime.until(LocalDateTime.of(2023, 2, 1, 12, 30, 56), ChronoUnit.YEARS);
System.out.println(until);//输出结果:3
}
LocalDateTime#format(...)
LocalDateTime#format(...)用于将当前 LocalDateTime 对象格式化为指定的日期时间字符串。
@Test
public void test15() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
String format = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(format);//输出结果:2020-02-01 12:18:56
}
LocalDateTime#atOffset(...)
LocalDateTime#atOffset() 主要是用于合并当前LocalDateTime对象与给定的偏移量。具体来说,该方法创建并返回一个 OffsetDateTime 对象,该对象将保存将当前LocalDateTime 与给定偏移量合并后的值。主要在需要对LocalDateTime对象进行偏移量调整的情况下使用。例如,如果你需要根据当前的LocalDateTime创建一个在特定偏移量(如一小时,一天)后的日期时间,就可以通过使用LocalDateTime#atOffset()方法来实现。这个方法的使用非常灵活,你可以根据需要选择不同的偏移量进行合并,得到的 OffsetDateTime 对象可以用于进一步的日期时间计算或展示等操作。
@Test
public void test16() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
OffsetDateTime offsetDateTime = localDateTime.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);//输出结果:2020-02-01T12:18:56+08:00
}
LocalDateTime#atZone(...)
LocalDateTime#atZone()用于将给定的LocalDateTime对象合并到给定的时区,从而创建一个ZonedDateTime对象。该方法是一个非静态方法,只能通过类对象访问。通过该方法,可以将在不同时区存储的日期时间数据统一到一个时区中进行处理和比较。
使用场景:
- 需要处理跨时区的日期时间数据时:在一些特定的应用场景中,可能需要对来自不同时区的日期时间数据进行处理和比较。例如,在跨国公司中,可能需要将不同地区的日期时间数据统一到一个时区中进行统计分析。在这种情况下,可以使用LocalDateTime#atZone()方法将LocalDateTime对象转换为ZonedDateTime对象,以便进行跨时区的日期时间操作。
- 需要确保日期时间数据的一致性时:在一些需要确保日期时间数据一致性的场景中,也可以使用LocalDateTime#atZone()方法。例如,在金融交易中,确保交易时间的准确性非常重要。通过使用该方法,可以将不同地区的日期时间数据转换为相同的时区,以确保交易时间的一致性。
@Test
public void test17() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
System.out.println(zonedDateTime);//输出结果:2020-02-01T12:18:56+08:00[Asia/Shanghai]
}
LocalDateTime#compareTo(...)、LocalDateTime#isAfter(...)、LocalDateTime#isBefore(...)、LocalDateTime#isEqual(...)
- compareTo(...):此方法用于比较当前LocalDateTime实例和其他日期时间的大小关系。它返回一个整数,如果当前实例大于、小于或等于给定的日期时间,则返回正整数、负整数或零。这个方法通常用于排序或比较日期时间的大小。
- isAfter(...):此方法用于检查作为参数传递的日期是否在此LocalDateTime实例之后。它返回一个布尔值,如果给定的日期时间小于当前实例,则返回false,否则返回true。这个方法通常用于判断某个日期时间是否在当前时间之后。
- isBefore(...):此方法的功能与isAfter()相反,用于检查作为参数传递的日期是否在此LocalDateTime实例之前。返回值与isAfter()相同,如果给定的日期时间大于当前实例,则返回false,否则返回true。这个方法通常用于判断某个日期时间是否在当前时间之前。
- isEqual(...):此方法用于检查作为参数传递的日期是否与当前LocalDateTime实例相等。它返回一个布尔值,如果两个实例的时间值完全相等,则返回true,否则返回false。这个方法通常用于比较两个日期时间是否完全相同。
@Test
public void test18() {
LocalDateTime localDateTime = LocalDateTime.of(2020, 2, 1, 12, 18, 56);
LocalDateTime localDateTime2 = LocalDateTime.of(2023, 2, 1, 12, 18, 56);
int compareTo = localDateTime2.compareTo(localDateTime);
System.out.println(compareTo);//输出结果:3
boolean before = localDateTime2.isBefore(localDateTime);
System.out.println(before);//输出结果:false
boolean after = localDateTime2.isAfter(localDateTime);
System.out.println(after);//输出结果:true
boolean equal = localDateTime2.isEqual(localDateTime);
System.out.println(equal);//输出结果:false
}
使用LocalDateTime的注意事项
在使用 LocalDateTime 时,有一些注意事项需要特别注意,了解这些限制和注意事项可以确保正确有效地使用它:
- 时区问题:LocalDateTime 不包含时区信息,这可能会导致在处理具有时区差异的日期和时间时出现问题。
- 精度问题:LocalDateTime 精度到秒,不包含毫秒,这可能在某些需要更高精度的情况下会限制其使用。
- 不可变对象:LocalDateTime 是一个不可变对象,这意味着对 LocalDateTime 对象的任何修改操作都会生成一个新的实例返回,而不会改变原来的对象。这使得多线程操作中无需考虑线程安全问题,因为本身 API 层面就不支持修改。
- 空指针异常:在使用 LocalDateTime 的 get 方法访问年、月、日等信息时,需要注意空指针异常的问题。可以使用 isPresent() 方法来检查是否存在值。
- 日期/时间格式化:LocalDateTime 没有提供内置的格式化方法,因此在使用时需要注意格式化问题。可以使用 DateTimeFormatter 类来进行日期/时间格式化。
- 与其它日期/时间类型的转换:在使用 LocalDateTime 时,可能需要将其与其它日期/时间类型进行转换,如 LocalDate、LocalTime、ZonedDateTime 等。在进行转换时,需要注意时区、精度等差异,以避免可能的问题。
- 时区处理:虽然 LocalDateTime 不包含时区信息,但在某些情况下可能需要考虑时区的影响。例如,在将 LocalDateTime 转换为 ZonedDateTime 时,需要提供时区信息。
- 时间戳的获取和比较:LocalDateTime 可以用于获取当前时间戳(以毫秒为单位)以及进行时间戳的比较。在进行时间戳比较时,需要注意时区、精度等差异。
- 与数据库中的日期/时间类型的转换:在将 LocalDateTime 与数据库中的日期/时间类型进行转换时,需要注意数据库中日期/时间的格式和类型,以及可能的时区差异。