Java Temporal 接口
最后修改时间:2025 年 4 月 16 日
java.time.temporal.Temporal 接口是一个框架级接口,用于表示日期时间对象。它提供了对日期时间字段的访问,并允许进行日期时间运算。像 LocalDate 和 ZonedDateTime 这样的类实现了这个接口。
Temporal 定义了查询和操作时间对象的操作。它支持添加或减去时间单位、比较日期以及访问时间字段。该接口支持对不同日期时间类型的多态处理。
Temporal 接口概述
Temporal 接口提供了用于时间算术和字段访问的方法。关键操作包括添加/减去时间、查询字段和调整值。它与 TemporalUnit 和 TemporalField 配合使用,以实现灵活的操作。
public interface Temporal extends TemporalAccessor {
boolean isSupported(TemporalUnit unit);
Temporal with(TemporalField field, long newValue);
Temporal plus(long amountToAdd, TemporalUnit unit);
Temporal minus(long amountToSubtract, TemporalUnit unit);
long until(Temporal endExclusive, TemporalUnit unit);
}
以上代码展示了 Temporal 接口的关键方法。这些方法可以操作时间对象,同时保持不可变性。实现类为这些操作提供了具体行为。
基本的时间操作
此示例演示了通过 Temporal 接口可用的基本操作。我们将使用实现 Temporal 的 LocalDate 来展示常见方法。操作包括添加时间和查询字段。
package com.zetcode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 4, 15);
// Add 2 weeks
Temporal futureDate = date.plus(2, ChronoUnit.WEEKS);
System.out.println("Date in 2 weeks: " + futureDate);
// Subtract 3 months
Temporal pastDate = date.minus(3, ChronoUnit.MONTHS);
System.out.println("Date 3 months ago: " + pastDate);
// Check if unit is supported
boolean supported = date.isSupported(ChronoUnit.DAYS);
System.out.println("Days supported: " + supported);
}
}
此示例展示了使用 LocalDate 的基本 Temporal 操作。plus 和 minus 方法返回新的 Temporal 对象。isSupported 方法检查时间单位是否可与时间对象一起使用。
使用 Temporal 进行字段调整
Temporal 接口允许修改日期时间对象的特定字段。这可以使用 with 方法完成,该方法返回一个新的调整后的对象。字段调整是精确的,并自动处理边缘情况。
package com.zetcode;
import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
public class Main {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.now();
System.out.println("Original: " + dateTime);
// Change year
Temporal newYear = dateTime.with(ChronoField.YEAR, 2030);
System.out.println("Year changed: " + newYear);
// Change hour
Temporal newHour = dateTime.with(ChronoField.HOUR_OF_DAY, 15);
System.out.println("Hour changed: " + newHour);
// Chain adjustments
Temporal adjusted = dateTime
.with(ChronoField.MONTH_OF_YEAR, 12)
.with(ChronoField.DAY_OF_MONTH, 25);
System.out.println("Christmas date: " + adjusted);
}
}
此示例演示了使用 Temporal 接口的字段调整。每个 with 操作都返回一个新的 Temporal 对象。多个调整可以链接在一起以创建复杂的转换。
计算 Temporal 之间的时间
until 方法以指定的单位计算两个时间对象之间的时间。这对于确定日期或时间之间的持续时间很有用。该方法会自动处理不同的时间类型。
package com.zetcode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate futureDate = today.plusMonths(3).plusDays(5);
// Days between dates
long daysBetween = today.until(futureDate, ChronoUnit.DAYS);
System.out.println("Days between: " + daysBetween);
// Months between dates
long monthsBetween = today.until(futureDate, ChronoUnit.MONTHS);
System.out.println("Months between: " + monthsBetween);
// Mixed types calculation
LocalDateTime now = LocalDateTime.now();
LocalDateTime later = now.plusHours(5).plusMinutes(30);
long minutesBetween = now.until(later, ChronoUnit.MINUTES);
System.out.println("Minutes between: " + minutesBetween);
}
}
此示例展示了如何计算时间对象之间的时间。until 方法适用于不同的时间类型和单位。请注意,计算是精确的,并遵守日历规则。
Temporal 与 TemporalAdjuster
Temporal 对象可以与 TemporalAdjusters 一起使用,以进行复杂的日期调整。调整器提供了预构建的操作,例如“下个星期二”或“当月最后一天”。这演示了 Temporal 接口的灵活性。
package com.zetcode;
import java.time.LocalDate;
import java.time.DayOfWeek;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 4, 15);
// Next Friday
Temporal nextFriday = date.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
System.out.println("Next Friday: " + nextFriday);
// Last day of month
Temporal monthEnd = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("Month end: " + monthEnd);
// First day of next year
Temporal yearStart = date.with(TemporalAdjusters.firstDayOfNextYear());
System.out.println("Next year start: " + yearStart);
// Custom adjuster (add 2 weeks)
Temporal custom = date.with(temporal -> temporal.plus(2, ChronoUnit.WEEKS));
System.out.println("Custom adjusted: " + custom);
}
}
此示例演示了将 TemporalAdjusters 与 Temporal 对象一起使用。调整器通过函数式接口提供常见的日期操作。也可以使用 lambda 表达式创建自定义调整器。
使用 TemporalQueries
Temporal 对象支持查询以提取信息。query 方法允许从时间对象中灵活地提取数据。这对于通用日期时间处理代码很有用。
package com.zetcode;
import java.time.LocalDateTime;
import java.time.temporal.TemporalQueries;
import java.time.temporal.TemporalQuery;
public class Main {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.now();
// Query for LocalDate
TemporalQuery<java.time.LocalDate> dateQuery = TemporalQueries.localDate();
java.time.LocalDate datePart = dateTime.query(dateQuery);
System.out.println("Date part: " + datePart);
// Query for time precision
TemporalQuery<java.time.temporal.ChronoUnit> precisionQuery =
TemporalQueries.precision();
java.time.temporal.ChronoUnit precision = dateTime.query(precisionQuery);
System.out.println("Precision: " + precision);
// Custom query (get day of week)
TemporalQuery<String> dayQuery =
temporal -> temporal.query(TemporalQueries.localDate())
.getDayOfWeek().toString();
String dayOfWeek = dateTime.query(dayQuery);
System.out.println("Day of week: " + dayOfWeek);
}
}
此示例展示了如何查询时间对象以获取信息。内置查询通过 TemporalQueries 提供,并且可以创建自定义查询。query 方法支持对不同时间类型的多态处理。
组合 Temporal 操作
此示例演示了组合多个 Temporal 操作以进行复杂的日期时间计算。我们将链接操作以创建涉及日期计算的业务逻辑场景。
package com.zetcode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
LocalDate projectStart = LocalDate.of(2025, 4, 15);
// Calculate project timeline
Temporal milestone1 = projectStart
.plus(2, ChronoUnit.WEEKS)
.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
Temporal milestone2 = ((LocalDate) milestone1)
.plus(3, ChronoUnit.WEEKS)
.with(TemporalAdjusters.lastDayOfMonth());
Temporal projectEnd = ((LocalDate) milestone2)
.plus(1, ChronoUnit.MONTHS)
.with(TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.FRIDAY));
System.out.println("Project start: " + projectStart);
System.out.println("Milestone 1: " + milestone1);
System.out.println("Milestone 2: " + milestone2);
System.out.println("Project end: " + projectEnd);
// Calculate total duration
long totalDays = projectStart.until(projectEnd, ChronoUnit.DAYS);
System.out.println("Total project days: " + totalDays);
}
}
此示例结合了多个 Temporal 操作来模拟项目时间线。我们使用 plus 操作、调整器和持续时间计算。请注意,当需要 LocalDate 中的特定方法时,需要进行类型转换。
来源
在本文中,我们介绍了 Java Temporal 接口的基本方法和功能。理解这些概念对于在现代 Java 应用程序中处理日期和时间至关重要。
作者
列出所有Java教程。