Java TemporalAmount 接口
最后修改时间:2025 年 4 月 16 日
java.time.temporal.TemporalAmount 接口表示一段时间。它可用于定义诸如“2 小时”或“5 天”之类的量。此接口由 Duration 和 Period 等类实现。
TemporalAmount 提供了从时间对象中添加或减去时间量的方法。它同时适用于基于日期和基于时间的时间量。该接口是 Java 8 中引入的 Java 现代日期时间 API 的一部分。
TemporalAmount 接口概述
TemporalAmount 接口定义了时间操作的方法。关键实现是 Duration(基于时间)和 Period(基于日期)。该接口支持跨不同时间类型进行灵活的时间计算。
public interface TemporalAmount {
long get(TemporalUnit unit);
List<TemporalUnit> getUnits();
Temporal addTo(Temporal temporal);
Temporal subtractFrom(Temporal temporal);
}
上面的代码显示了 TemporalAmount 定义的方法。这些方法允许查询单位、获取值和执行时间算术运算。实现必须处理单位转换和边界条件。
将 Duration 与 TemporalAmount 一起使用
Duration 是 TemporalAmount 的一个基于时间的实现。它表示以秒和纳秒为单位的一段时间。Duration 非常适合精确的时间测量。
package com.zetcode;
import java.time.Duration;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
Duration duration = Duration.ofHours(2).plusMinutes(30);
// Get units
System.out.println("Units: " + duration.getUnits());
// Get value in seconds
System.out.println("Seconds: " + duration.getSeconds());
// Add to temporal object
LocalTime time = LocalTime.of(10, 0);
LocalTime newTime = (LocalTime) duration.addTo(time);
System.out.println("New time: " + newTime);
// Subtract from temporal object
LocalTime earlierTime = (LocalTime) duration.subtractFrom(time);
System.out.println("Earlier time: " + earlierTime);
}
}
此示例演示了将 Duration 用作 TemporalAmount。我们创建一个 2.5 小时的持续时间,然后将其添加到 LocalTime 并从中减去。getUnits() 方法显示持续时间包含哪些时间单位。
将 Period 与 TemporalAmount 一起使用
Period 是 TemporalAmount 的一个基于日期的实现。它表示以年、月和天为单位的一段时间。Period 适用于基于日历的日期计算。
package com.zetcode;
import java.time.LocalDate;
import java.time.Period;
public class Main {
public static void main(String[] args) {
Period period = Period.ofYears(1).plusMonths(2).plusDays(3);
// Get units
System.out.println("Units: " + period.getUnits());
// Get values
System.out.println("Years: " + period.getYears());
System.out.println("Months: " + period.getMonths());
System.out.println("Days: " + period.getDays());
// Add to temporal object
LocalDate date = LocalDate.of(2025, 1, 1);
LocalDate newDate = (LocalDate) period.addTo(date);
System.out.println("New date: " + newDate);
}
}
此示例显示了 Period 被用作 TemporalAmount。我们创建一个 1 年 2 个月 3 天的 Period,然后将其添加到 LocalDate。Period 自动处理日历感知日期算术。
自定义 TemporalAmount 实现
我们可以创建 TemporalAmount 的自定义实现,用于专门的时间计算。此示例显示了一个简单的实现,仅代表工作日。
package com.zetcode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalUnit;
import java.util.Collections;
import java.util.List;
public class Main {
static class BusinessDays implements TemporalAmount {
private final long days;
public BusinessDays(long days) {
this.days = days;
}
@Override
public Temporal addTo(Temporal temporal) {
LocalDate date = LocalDate.from(temporal);
long added = 0;
while (added < days) {
date = date.plus(1, ChronoUnit.DAYS);
if (date.getDayOfWeek().getValue() < 6) {
added++;
}
}
return temporal.with(date);
}
@Override
public Temporal subtractFrom(Temporal temporal) {
return addTo(temporal).minus(days * 2, ChronoUnit.DAYS);
}
@Override
public long get(TemporalUnit unit) {
if (unit == ChronoUnit.DAYS) {
return days;
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
@Override
public List getUnits() {
return Collections.singletonList(ChronoUnit.DAYS);
}
}
public static void main(String[] args) {
BusinessDays businessDays = new BusinessDays(5);
LocalDate startDate = LocalDate.of(2025, 4, 1); // Tuesday
LocalDate endDate = (LocalDate) businessDays.addTo(startDate);
System.out.println("Start date: " + startDate);
System.out.println("End date (5 business days later): " + endDate);
}
}
此示例演示了一个自定义 TemporalAmount,它跳过周末。BusinessDays 类在执行日期算术时仅添加工作日。这展示了如何为业务应用程序创建专门的时间计算。
组合 TemporalAmount 实现
我们可以组合不同的 TemporalAmount 实现以进行复杂的时间计算。此示例混合了 Period 和 Duration 以获得完整的时间跨度。
package com.zetcode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.TemporalAmount;
public class Main {
public static void main(String[] args) {
// Date-based amount
Period period = Period.of(1, 2, 3); // 1 year, 2 months, 3 days
// Time-based amount
Duration duration = Duration.ofHours(4).plusMinutes(30);
LocalDateTime dateTime = LocalDateTime.of(2025, 1, 1, 10, 0);
System.out.println("Original: " + dateTime);
// Apply period first (date-based)
LocalDateTime afterPeriod = (LocalDateTime) period.addTo(dateTime);
System.out.println("After period: " + afterPeriod);
// Then apply duration (time-based)
LocalDateTime afterBoth = (LocalDateTime) duration.addTo(afterPeriod);
System.out.println("After both: " + afterBoth);
// Combined operation
LocalDateTime combined = dateTime
.plus(period)
.plus(duration);
System.out.println("Combined result: " + combined);
}
}
此示例显示了如何组合 Period 和 Duration 操作。我们首先添加一个 Period(基于日期),然后添加一个 Duration(基于时间)到 LocalDateTime。结果演示了使用多个 TemporalAmounts 的复杂时间算术运算。
查询 TemporalAmount 值
TemporalAmount 接口提供了查询其组成值的方法。此示例显示了如何检查不同时间量的单位和值。
package com.zetcode;
import java.time.Duration;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalUnit;
public class Main {
public static void main(String[] args) {
TemporalAmount[] amounts = {
Period.of(1, 2, 3),
Duration.ofHours(2).plusMinutes(30),
Duration.ofDays(1).plusHours(6)
};
for (TemporalAmount amount : amounts) {
System.out.println("\nAmount: " + amount);
System.out.println("Units: " + amount.getUnits());
for (TemporalUnit unit : amount.getUnits()) {
System.out.println(unit + ": " + amount.get(unit));
}
}
// Custom query for specific unit
Duration duration = Duration.ofMinutes(90);
long hours = duration.get(ChronoUnit.HOURS);
long minutes = duration.get(ChronoUnit.MINUTES);
System.out.println("\n90 minutes = " + hours + " hours " +
(minutes - hours * 60) + " minutes");
}
}
此示例演示了如何查询 TemporalAmount 对象的组成部分。我们检查 Period 和 Duration 实例,显示它们的单位和值。get() 方法允许从量中访问特定的单位值。
将 TemporalAmount 与 TemporalAdjuster 一起使用
TemporalAmount 可与 TemporalAdjuster 一起使用,以进行更复杂的日期操作。此示例显示了组合这些接口以进行灵活的日期计算。
package com.zetcode;
import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAmount;
public class Main {
static class NextBusinessDayAdjuster implements TemporalAdjuster {
private final TemporalAmount amount;
public NextBusinessDayAdjuster(TemporalAmount amount) {
this.amount = amount;
}
@Override
public Temporal adjustInto(Temporal temporal) {
Temporal adjusted = amount.addTo(temporal);
LocalDate date = LocalDate.from(adjusted);
// Adjust to next business day if needed
while (date.getDayOfWeek().getValue() >= 6) {
date = date.plusDays(1);
}
return temporal.with(date);
}
}
public static void main(String[] args) {
TemporalAmount twoDays = Period.ofDays(2);
TemporalAdjuster adjuster = new NextBusinessDayAdjuster(twoDays);
LocalDate friday = LocalDate.of(2025, 4, 4); // Friday
LocalDate nextBusinessDay = friday.with(adjuster);
System.out.println("Friday: " + friday);
System.out.println("Two business days later: " + nextBusinessDay);
// Using with Period
Period period = Period.ofWeeks(1);
LocalDate inOneWeek = friday.with(new NextBusinessDayAdjuster(period));
System.out.println("One business week later: " + inOneWeek);
}
}
此示例将 TemporalAmount 与 TemporalAdjuster 结合使用,以创建业务日感知的日期计算。调整器确保结果落在工作日,即使添加标准时间量也是如此。这展示了强大的时间操作。
来源
在本文中,我们介绍了 Java TemporalAmount 接口的基本方法和特性。理解这些概念对于在现代 Java 应用程序中灵活地处理时间至关重要。
作者
列出所有Java教程。