Java TemporalField 接口
最后修改时间:2025 年 4 月 16 日
java.time.temporal.TemporalField 接口表示日期时间的字段,例如年中的月份或小时。 它提供了一种通用的访问日期时间字段的方式。 TemporalField 是 Java Time API 中的关键接口。
TemporalField 定义了在时间对象上获取和设置字段值的方法。 它适用于日期和时间字段。 该接口由 ChronoField 枚举和自定义字段实现来实现。
TemporalField 接口概述
TemporalField 提供了访问字段值和执行验证的方法。 关键操作包括获取值范围和检查支持。 该接口支持跨不同时间类型的通用字段访问。
public interface TemporalField {
TemporalUnit getBaseUnit();
TemporalUnit getRangeUnit();
ValueRange range();
boolean isDateBased();
boolean isTimeBased();
boolean isSupportedBy(TemporalAccessor temporal);
ValueRange rangeRefinedBy(TemporalAccessor temporal);
long getFrom(TemporalAccessor temporal);
<R extends Temporal> R adjustInto(R temporal, long newValue);
}
上面的代码显示了 TemporalField 的关键方法。 这些方法允许以通用方式访问和操作时间字段。 该接口支持基于日期和基于时间的字段。
访问字段值
getFrom 方法从时间对象中检索字段值。 这适用于支持该字段的任何时间类型。 该方法将字段值作为 long 类型返回。
package com.zetcode;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 4, 16);
LocalTime time = LocalTime.of(14, 30);
// Get day-of-month from date
long dayOfMonth = ChronoField.DAY_OF_MONTH.getFrom(date);
System.out.println("Day of month: " + dayOfMonth);
// Get hour-of-day from time
long hourOfDay = ChronoField.HOUR_OF_DAY.getFrom(time);
System.out.println("Hour of day: " + hourOfDay);
// Get month-of-year from date
long monthOfYear = ChronoField.MONTH_OF_YEAR.getFrom(date);
System.out.println("Month of year: " + monthOfYear);
}
}
此示例演示了使用 TemporalField 获取字段值。 我们使用实现了该接口的 ChronoField 常量。 该方法在不同的时间类型之间一致地工作。
检查字段支持
在访问字段之前,我们应该检查时间对象是否支持它。 isSupportedBy 方法验证字段支持。 这可以防止运行时异常。
package com.zetcode;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
// Check date field support
System.out.println("DAY_OF_MONTH supported in date: " +
ChronoField.DAY_OF_MONTH.isSupportedBy(date));
System.out.println("HOUR_OF_DAY supported in date: " +
ChronoField.HOUR_OF_DAY.isSupportedBy(date));
// Check time field support
System.out.println("HOUR_OF_DAY supported in time: " +
ChronoField.HOUR_OF_DAY.isSupportedBy(time));
System.out.println("MONTH_OF_YEAR supported in time: " +
ChronoField.MONTH_OF_YEAR.isSupportedBy(time));
}
}
此示例在访问前检查字段支持。 日期对象通常不支持时间字段,反之亦然。 该方法有助于编写处理不同类型的可靠时间代码。
获取字段值范围
字段具有随上下文变化的有效值范围。 range 方法提供此信息。 它们有助于在设置之前验证值。
package com.zetcode;
import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.ValueRange;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 2, 1); // February 2025 (not leap)
// Get general range for day-of-month
ValueRange generalRange = ChronoField.DAY_OF_MONTH.range();
System.out.println("General day-of-month range: " + generalRange);
// Get specific range for this date
ValueRange specificRange = ChronoField.DAY_OF_MONTH.rangeRefinedBy(date);
System.out.println("Specific day-of-month range: " + specificRange);
// Get range for month-of-year
ValueRange monthRange = ChronoField.MONTH_OF_YEAR.range();
System.out.println("Month-of-year range: " + monthRange);
}
}
此示例显示了字段范围访问方法。 一般范围是固定的,而精细范围考虑了上下文,例如月份长度。 范围信息对于验证至关重要。
调整时间对象
adjustInto 方法通过设置字段值来修改时间对象。 它返回一个新的调整后的对象,同时保持原始对象不变。 这遵循了不可变模式。
package com.zetcode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
public class Main {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 4, 16);
LocalDateTime dateTime = LocalDateTime.of(2025, 4, 16, 14, 30);
// Adjust day-of-month
LocalDate adjustedDate = (LocalDate) ChronoField.DAY_OF_MONTH.adjustInto(date, 25);
System.out.println("Adjusted date: " + adjustedDate);
// Adjust hour-of-day
LocalDateTime adjustedDateTime = (LocalDateTime)
ChronoField.HOUR_OF_DAY.adjustInto(dateTime, 18);
System.out.println("Adjusted date-time: " + adjustedDateTime);
// Chain adjustments
LocalDateTime finalDateTime = (LocalDateTime)
ChronoField.MINUTE_OF_HOUR.adjustInto(
ChronoField.HOUR_OF_DAY.adjustInto(dateTime, 9), 15);
System.out.println("Final date-time: " + finalDateTime);
}
}
此示例演示了使用 TemporalField 进行时间调整。 该方法需要转换为特定的时间类型。 可以链接多个调整以进行复杂的修改。
使用自定义时间字段
我们可以为自定义字段实现 TemporalField。 这需要定义字段行为和范围规则。 自定义字段与 Java Time API 集成。
package com.zetcode;
import java.time.LocalDate;
import java.time.temporal.TemporalField;
import java.time.temporal.ValueRange;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
public class Main {
static final TemporalField QUARTER_OF_YEAR = new TemporalField() {
@Override
public TemporalUnit getBaseUnit() {
return ChronoUnit.MONTHS;
}
@Override
public TemporalUnit getRangeUnit() {
return ChronoUnit.YEARS;
}
@Override
public ValueRange range() {
return ValueRange.of(1, 4);
}
@Override
public boolean isDateBased() {
return true;
}
@Override
public boolean isTimeBased() {
return false;
}
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(ChronoField.MONTH_OF_YEAR);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
return range();
}
@Override
public long getFrom(TemporalAccessor temporal) {
int month = temporal.get(ChronoField.MONTH_OF_YEAR);
return (month - 1) / 3 + 1;
}
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
int currentQuarter = getFrom(temporal);
int monthChange = (int) ((newValue - currentQuarter) * 3);
return (R) temporal.plus(monthChange, ChronoUnit.MONTHS);
}
};
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 15);
// Get quarter from custom field
long quarter = QUARTER_OF_YEAR.getFrom(date);
System.out.println("Quarter: " + quarter);
// Adjust to different quarter
LocalDate q4Date = (LocalDate) QUARTER_OF_YEAR.adjustInto(date, 4);
System.out.println("Q4 date: " + q4Date);
}
}
此示例显示了一个自定义的季度字段实现。 该字段根据月份计算季度并允许进行调整。 自定义字段必须正确实现所有接口方法。
将 TemporalField 与 TemporalQueries 结合使用
TemporalField 可以与 TemporalQuery 一起使用,以实现灵活的时间访问。 这种组合支持强大的日期时间操作和查询。
package com.zetcode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalQuery;
public class Main {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.of(2025, 4, 16, 14, 30);
// Query for month value
TemporalQuery<Long> monthQuery = ChronoField.MONTH_OF_YEAR::getFrom;
Long month = dateTime.query(monthQuery);
System.out.println("Month from query: " + month);
// Query for hour value
TemporalQuery<Long> hourQuery = ChronoField.HOUR_OF_DAY::getFrom;
Long hour = dateTime.query(hourQuery);
System.out.println("Hour from query: " + hour);
// Combined query
TemporalQuery<String> combinedQuery = temporal -> {
long y = temporal.get(ChronoField.YEAR);
long m = temporal.get(ChronoField.MONTH_OF_YEAR);
long d = temporal.get(ChronoField.DAY_OF_MONTH);
return String.format("%d-%02d-%02d", y, m, d);
};
String formatted = dateTime.query(combinedQuery);
System.out.println("Formatted date: " + formatted);
}
}
此示例演示了将 TemporalField 与查询结合使用。 字段引用可以直接用作查询。 更复杂的查询可以组合多个字段以获得自定义结果。
来源
在本文中,我们涵盖了 Java TemporalField 接口的基本方法和特性。 了解这些概念对于在 Java 应用程序中处理日期和时间字段至关重要。
作者
列出所有Java教程。