Java TemporalUnit 接口
最后修改时间:2025 年 4 月 16 日
java.time.temporal.TemporalUnit
接口表示一个时间单位。它是 Java 8 中引入的 Java 日期和时间 API 的一部分。TemporalUnit 定义了如何度量和操作时间单位。
TemporalUnit
由 ChronoUnit
枚举实现,该枚举提供了标准单位,如秒、分钟、小时、天等。该接口允许创建自定义时间单位。它与时间对象(如 Instant 和 LocalDateTime)一起使用。
TemporalUnit 接口概述
TemporalUnit
接口定义了用于查询和操作时间对象的方法。关键操作包括检查持续时间、添加到时间对象以及估计长度。该接口支持灵活的时间计算。
public interface TemporalUnit { Duration getDuration(); boolean isDurationEstimated(); boolean isDateBased(); boolean isTimeBased(); boolean isSupportedBy(Temporal temporal); <R extends Temporal> R addTo(R temporal, long amount); long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive); String toString(); }
上面的代码显示了 TemporalUnit
的关键方法。这些方法允许查询单位特征并执行时间算术。该接口是 Java 中基于时间计算的基础。
使用 ChronoUnit 常量
ChronoUnit
枚举提供了 TemporalUnit 的标准实现。这些常量表示常见的的时间单位,从纳秒到世纪。它们是使用 TemporalUnit 的最常见方式。
package com.zetcode; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); // Add 5 hours LocalDateTime later = now.plus(5, ChronoUnit.HOURS); System.out.println("5 hours later: " + later); // Subtract 3 days LocalDateTime earlier = now.minus(3, ChronoUnit.DAYS); System.out.println("3 days earlier: " + earlier); // Check if time-based System.out.println("Is DAYS time-based? " + ChronoUnit.DAYS.isTimeBased()); // Check if date-based System.out.println("Is HOURS date-based? " + ChronoUnit.HOURS.isDateBased()); } }
此示例演示了将 ChronoUnit 常量与 LocalDateTime 一起使用。plus
和 minus
方法接受 TemporalUnit 参数。ChronoUnit 提供了基于时间和基于日期的单位。
检查单位特性
TemporalUnit 提供了检查单位属性的方法。这些包括一个单位是基于时间的、基于日期的,还是具有估计的持续时间。此信息对于验证和条件逻辑很有用。
package com.zetcode; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { // Check unit characteristics System.out.println("NANOS duration: " + ChronoUnit.NANOS.getDuration()); System.out.println("Is YEARS estimated? " + ChronoUnit.YEARS.isDurationEstimated()); // Time-based vs date-based System.out.println("SECONDS isTimeBased: " + ChronoUnit.SECONDS.isTimeBased()); System.out.println("MONTHS isDateBased: " + ChronoUnit.MONTHS.isDateBased()); // Mixed units System.out.println("WEEKS isTimeBased: " + ChronoUnit.WEEKS.isTimeBased()); System.out.println("WEEKS isDateBased: " + ChronoUnit.WEEKS.isDateBased()); } }
此示例展示了如何查询 TemporalUnit 的特征。请注意,有些单位(如 WEEKS)既不是基于时间也不是基于日期的。基于日期的单位的持续时间可能由于月份长度的变化而有所估计。
计算日期之间的时间
between
方法以特定单位计算两个时间对象之间的时间。这对于以不同单位测量持续时间很有用。计算会尊重日历规则(如果适用)。
package com.zetcode; import java.time.LocalDate; import java.time.LocalTime; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { LocalDate date1 = LocalDate.of(2025, 1, 1); LocalDate date2 = LocalDate.of(2025, 6, 15); // Calculate difference in days long daysBetween = ChronoUnit.DAYS.between(date1, date2); System.out.println("Days between: " + daysBetween); // Calculate difference in months long monthsBetween = ChronoUnit.MONTHS.between(date1, date2); System.out.println("Months between: " + monthsBetween); LocalTime time1 = LocalTime.of(8, 30); LocalTime time2 = LocalTime.of(14, 45); // Calculate difference in hours double hoursBetween = ChronoUnit.HOURS.between(time1, time2); System.out.println("Hours between: " + hoursBetween); } }
此示例演示了使用 TemporalUnit 计算时间差。between
方法以指定的单位返回数量。对于基于日期的单位,计算会考虑日历规则。
创建自定义 TemporalUnit
虽然 ChronoUnit 涵盖了大多数需求,但您可以为自定义时间单位实现 TemporalUnit。这需要实现所有接口方法。该示例显示了一个简单的工作周单位。
package com.zetcode; import java.time.Duration; import java.time.LocalDate; import java.time.temporal.Temporal; import java.time.temporal.TemporalUnit; import java.util.List; public class Main { static class WorkWeekUnit implements TemporalUnit { @Override public Duration getDuration() { return Duration.ofDays(5); } @Override public boolean isDurationEstimated() { return false; } @Override public boolean isDateBased() { return true; } @Override public boolean isTimeBased() { return false; } @Override public boolean isSupportedBy(Temporal temporal) { return temporal.isSupported(ChronoUnit.DAYS); } @Override public Temporal addTo(Temporal temporal, long amount) { return temporal.plus(amount * 5, ChronoUnit.DAYS); } @Override public long between(Temporal temporal1, Temporal temporal2) { return ChronoUnit.DAYS.between(temporal1, temporal2) / 5; } @Override public String toString() { return "WorkWeek"; } } public static void main(String[] args) { WorkWeekUnit workWeek = new WorkWeekUnit(); LocalDate startDate = LocalDate.of(2025, 1, 1); // Add 2 work weeks LocalDate endDate = (LocalDate) workWeek.addTo(startDate, 2); System.out.println("After 2 work weeks: " + endDate); // Calculate work weeks between long weeks = workWeek.between(startDate, endDate); System.out.println("Work weeks between: " + weeks); } }
此示例显示了自定义 WorkWeekUnit 的实现。该单位将 5 天视为一个工作周。所有 TemporalUnit 方法都已实现以支持此自定义时间度量。
将 TemporalUnit 与 Duration 结合使用
TemporalUnit 与 Duration 配合使用,可以进行精确的时间计算。Duration 可以从 TemporalUnit 的 getDuration 方法创建。这支持基于时间的灵活操作。
package com.zetcode; import java.time.Duration; import java.time.LocalTime; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { // Get duration of different units Duration hourDuration = ChronoUnit.HOURS.getDuration(); System.out.println("Duration of HOURS: " + hourDuration); Duration dayDuration = ChronoUnit.DAYS.getDuration(); System.out.println("Duration of DAYS: " + dayDuration); // Use with LocalTime LocalTime time = LocalTime.of(9, 0); LocalTime newTime = time.plus(hourDuration.multipliedBy(3)); System.out.println("Time after 3 hours: " + newTime); // Compare durations System.out.println("Is HOURS shorter than DAYS? " + (hourDuration.compareTo(dayDuration) < 0)); } }
此示例演示了 TemporalUnit 和 Duration 之间的关系。getDuration
方法提供了一个单位的标准持续时间。持续时间可以直接用于时间计算中。
验证单位支持
并非所有时间对象都支持所有单位。isSupportedBy
方法检查一个单位是否可以与特定的时间对象一起使用。这可以防止出现不支持的操作异常。
package com.zetcode; import java.time.LocalDate; import java.time.LocalTime; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { LocalDate date = LocalDate.now(); LocalTime time = LocalTime.now(); // Check date support System.out.println("MONTHS supported by date: " + ChronoUnit.MONTHS.isSupportedBy(date)); System.out.println("HOURS supported by date: " + ChronoUnit.HOURS.isSupportedBy(date)); // Check time support System.out.println("SECONDS supported by time: " + ChronoUnit.SECONDS.isSupportedBy(time)); System.out.println("DAYS supported by time: " + ChronoUnit.DAYS.isSupportedBy(time)); // Try to use unsupported unit if (ChronoUnit.YEARS.isSupportedBy(time)) { time = time.plus(1, ChronoUnit.YEARS); } else { System.out.println("Cannot add YEARS to LocalTime"); } } }
此示例显示了如何在执行操作之前检查单位支持。LocalDate 支持基于日期的单位,而 LocalTime 支持基于时间的单位。此检查可防止尝试使用不兼容的单位。
来源
在本文中,我们介绍了 Java TemporalUnit 接口的基本方法和特性。理解这些概念对于在现代 Java 应用程序中灵活处理时间至关重要。
作者
列出所有Java教程。