Java 根据现有实例创建日期和时间,用户希望修改 Date-Time API 中某个类的现有实例,如果需要进行简单的增减操作,使用 plus 或 minus 方法;对于其他操作,使用 with 方法。Date-Time API 中的所有实例都是不可变的。一旦创建 LocalDate、LocalTime、LocalDateTime 或 ZonedDateTime,就无法修改它们。
Java 根据现有实例创建日期和时间 问题描述
用户希望修改 Date-Time API 中某个类的现有实例。
Java 根据现有实例创建日期和时间 解决方案
如果需要进行简单的增减操作,使用 plus 或 minus 方法;对于其他操作,使用 with 方法。
Java 根据现有实例创建日期和时间 具体实例
Date-Time API 中的所有实例都是不可变的。一旦创建 LocalDate、LocalTime、LocalDateTime 或 ZonedDateTime,就无法修改它们。这对保持线程安全而言十分有利,不过如何根据现有实例创建新的实例呢?
以 LocalDate 类为例,它定义了多种对日期进行增减操作的方法,包括:
LocalDate plusDays(long daysToAdd)
LocalDate plusWeeks(long weeksToAdd)
LocalDate plusMonths(long monthsToAdd)
LocalDate plusYears(long yearsToAdd)
上述方法均返回一个新的 LocalDate,它是当前日期的副本,并添加了指定的值。
LocalTime 类也定义了类似的方法:
LocalTime plusNanos(long nanosToAdd)
LocalTime plusSeconds(long secondsToAdd)
LocalTime plusMinutes(long minutesToAdd)
LocalTime plusHours(long hoursToAdd)
类似地,每种方法均返回一个新的 LocalTime,它是当前时间的副本,并添加了指定的值。此外,LocalDateTime 类囊括了 LocalDate 和 LocalTime 类中用于处理日期和时间增减的所有方法。例 8-6 显示了各种 plus 方法在 LocalDate 和 LocalTime 类中的应用。
例 8-6 plus 方法在 LocalDate 和 LocalTime 类中的应用
不少类还包括其他两种形式的 plus 和 minus 方法。以 LocalDateTime 类为例,plus 和 minus 方法的签名如下:
对于 LocalDate 和 LocalDate 类,plus 和 minus 方法的格式与 LocalDateTime 类相同,具有相应的返回类型。有趣的是,不妨将 minus 方法视为具有否定形式的 plus 方法。
对传入 TemporalAmount 的方法而言,参数通常为 Period 或 Duration,但也可以是任何实现 TemporalAmount 接口的类型。该接口定义了 addTo 和 subtractFrom 两种方法:
跟踪调用栈(call stack)可以看到,调用 minus 委托给带有否定参数的 plus,而 plus 委托给 TemporalAmount.addTo(Temporal),TemporalAmount.addTo(Temporal) 再回调 plus(long, TemporalUnit),它将执行实际的操作。
例 8-7 显示了 plus 和 minus 方法的相关应用。
例 8-7 plus 和 minus 方法的应用
当 API 调用 TemporalUnit 时,提供的实现类为 ChronoUnit,它定义了许多方便的枚举常量(enum constant)可供使用。
此外,每种类都定义了一系列 with 方法,可以一次修改一个字段。
with 方法用于处理常用的日期和时间,某些方法颇为有趣。以 LocalDateTime 类为例:
例 8-8 显示了各种 with 方法的应用。
例 8-8 with 方法在 LocalDateTime 类中的应用
由于 2017 年并非闰年,无法将日期设置为 2 月 29 日,第二个测试将抛出 DateTimeException。
with 方法也可以传入 TemporalAdjuster 或 TemporalField:
传入 TemporalField 的 with 方法允许字段解析日期以使其有效。如例 8-9 所示,程序传入 1 月的最后一天,并尝试将月份改为 2 月(“2 月 31 日”)。此时,根据 Javadoc 的描述,系统将选择前一个有效日期,即 2 月的最后一天(2 月 28 日)。
例 8-9 月份调整(无效)
可想而知,日期和时间的处理涉及一些相当复杂的规则,不过 Javadoc 对此做了系统而详尽的描述。
范例调节器与查询将讨论传入 TemporalAdjuster 的 with 方法。