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教程。