Java TemporalField Interface
Last modified: April 16, 2025
The java.time.temporal.TemporalField interface represents a field of
date-time, such as month-of-year or hour-of-day. It provides access to date-time
fields in a generic way. TemporalField is a key interface in the Java Time API.
TemporalField defines methods to get and set field values on
temporal objects. It works with both date and time fields. The interface is
implemented by ChronoField enum and custom field implementations.
TemporalField Interface Overview
TemporalField provides methods to access field values and perform
validations. Key operations include getting value ranges and checking support.
The interface enables generic field access across different temporal types.
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);
}
The code above shows key methods of TemporalField. These methods
allow accessing and manipulating temporal fields generically. The interface
supports both date-based and time-based fields.
Accessing Field Values
The getFrom method retrieves field values from temporal objects.
This works with any temporal type that supports the field. The method returns
the field value as a 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);
}
}
This example demonstrates getting field values using TemporalField.
We use ChronoField constants which implement the interface. The
method works consistently across different temporal types.
Checking Field Support
Before accessing a field, we should check if it's supported by the temporal
object. The isSupportedBy method verifies field support. This
prevents runtime exceptions.
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));
}
}
This example checks field support before access. Date objects typically don't support time fields and vice versa. The method helps write robust temporal code that handles different types.
Getting Field Value Ranges
Fields have valid value ranges that vary by context. The range
methods provide this information. They help validate values before setting.
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);
}
}
This example shows field range access methods. The general range is fixed, while refined range considers context like month length. Range information is crucial for validation.
Adjusting Temporal Objects
The adjustInto method modifies temporal objects by setting field
values. It returns a new adjusted object while keeping the original unchanged.
This follows the immutable pattern.
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);
}
}
This example demonstrates temporal adjustments using TemporalField.
The method requires casting to the specific temporal type. Multiple adjustments
can be chained for complex modifications.
Working with Custom Temporal Fields
We can implement TemporalField for custom fields. This requires
defining field behavior and range rules. Custom fields integrate with the
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);
}
}
This example shows a custom quarter-of-year field implementation. The field calculates quarters from months and allows adjustments. Custom fields must properly implement all interface methods.
Combining TemporalField with TemporalQueries
TemporalField can be used with TemporalQuery for
flexible temporal access. This combination enables powerful date-time
manipulations and queries.
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);
}
}
This example demonstrates combining TemporalField with queries.
Field references can be used directly as queries. More complex queries can
combine multiple fields for custom results.
Source
Java TemporalField Interface Documentation
In this article, we've covered the essential methods and features of the Java TemporalField interface. Understanding these concepts is crucial for working with date and time fields in Java applications.
Author
List all Java tutorials.