o7planning

Java TemporalAccessor Tutorial with Examples

  1. TemporalAccessor
  2. TemporalAccessor methods
  3. query(TemporalQuery<R>)
  4. range(TemporalField)
  5. get(TemporalField)
  6. getLong(TemporalField)
  7. isSupported(TemporalField)

1. TemporalAccessor

The TemporalAccessor interface simulates a common concept between the concepts of date, time, time offset, time-zone offset and era. It provides basic methods to get information from these objects.
public interface TemporalAccessor
List of subclasses or enum(s) that implement the TemporalAccessor interface:
TemporalAccessor is a framework-level interface. Be careful when using it in your application because it is a base interface of various calendar systems supported in Java Date Time API. See the ChronoLocalDate interface for a more detailed discussion.
  • Java ChronoLocalDate
Note: If you intend to write classes that implement the TemporalAccessor interface, you should write classes with immutability to be consistent with the Java Date Time API (Although this is not required).

2. TemporalAccessor methods

public boolean isSupported(TemporalField field);

public default ValueRange range(TemporalField field)  

public default int get(TemporalField field)  

public long getLong(TemporalField field);

public default <R> R query(TemporalQuery<R> query)

3. query(TemporalQuery<R>)

Query this TemporalAccessor object with the specified TemporalQuery object to extract information.
public default <R> R query(TemporalQuery<R> query)
See examples of this topic in the article about TemporalQuery:

4. range(TemporalField)

Return a ValueRange object that describes a range of valid values for the specified field. This is a default method of TemporalAccessor interface. It can be overridden in subclasses of TemporalAccessor.
public default ValueRange range(TemporalField field) {
    if (field instanceof ChronoField) {
        if (isSupported(field)) {
            return field.range();
        }
        throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    }
    Objects.requireNonNull(field, "field");
    return field.rangeRefinedBy(this);
}
Basically, the ValueRange object contains the minimum and maximum value of a given field in a long data type. If the specified field is not ranged or not supported, an UnsupportedTemporalTypeException is thrown.
ChronoField is an enum that implements the TemporalField interface, which contains standard fields and is sufficient for use in the Java Date Time API.
  • ChronoField.DAY_OF_WEEK
  • ChronoField.DAY_OF_YEAR
  • ChronoField.HOUR_OF_DAY
  • ...
TemporalAccessor_range_x1.java
package org.o7planning.temporalaccessor.ex;

import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.ValueRange;

public class TemporalAccessor_range_x1 {

    public static void main(String[] args) {

        TemporalAccessor localDateTime = LocalDateTime.of(2021, 2, 15, 0, 0, 0);
        System.out.printf("localDateTime: %s%n%n", localDateTime); // 2021-02-15T00:00

        if (localDateTime.isSupported(ChronoField.HOUR_OF_DAY)) {
            ValueRange valueRange1 = localDateTime.range(ChronoField.HOUR_OF_DAY);

            System.out.println("HOUR_OF_DAY range: " + valueRange1); // 0 - 23
            System.out.println("valueRange1.getMinimum(): " + valueRange1.getMinimum()); // 0
            System.out.println("valueRange1.getMaximum(): " + valueRange1.getMaximum()); // 23
        }
        System.out.println(" --------- ");

        if (localDateTime.isSupported(ChronoField.DAY_OF_MONTH)) {
            ValueRange valueRange2 = localDateTime.range(ChronoField.DAY_OF_MONTH);

            System.out.println("DAY_OF_MONTH range: " + valueRange2); // 1 - 28
            System.out.println("valueRange2.getMinimum(): " + valueRange2.getMinimum()); // 1
            System.out.println("valueRange2.getMaximum(): " + valueRange2.getMaximum()); // 28
        }

        System.out.println(" --------- ");

        if (localDateTime.isSupported(ChronoField.DAY_OF_YEAR)) {
            ValueRange valueRange3 = localDateTime.range(ChronoField.DAY_OF_YEAR);

            System.out.println("DAY_OF_MONTH range: " + valueRange3); // 1 - 365
            System.out.println("valueRange3.getMinimum(): " + valueRange3.getMinimum()); // 1
            System.out.println("valueRange3.getMaximum(): " + valueRange3.getMaximum()); // 365
        }
    }
}
Output:
localDateTime: 2021-02-15T00:00

HOUR_OF_DAY range: 0 - 23
valueRange1.getMinimum(): 0
valueRange1.getMaximum(): 23
 ---------
DAY_OF_MONTH range: 1 - 28
valueRange2.getMinimum(): 1
valueRange2.getMaximum(): 28
 ---------
DAY_OF_MONTH range: 1 - 365
valueRange3.getMinimum(): 1
valueRange3.getMaximum(): 365
  • TemporalField
  • ChronoField

5. get(TemporalField)

Return the value of the specified field from this TemporalAccessor object as a 32-bit integer.
public default int get(TemporalField field) {
    ValueRange range = range(field);
    if (range.isIntValue() == false) {
        throw new UnsupportedTemporalTypeException("Invalid field " + field + " for get() method, use getLong() instead");
    }
    long value = getLong(field);
    if (range.isValidValue(value) == false) {
        throw new DateTimeException("Invalid value for " + field + " (valid values " + range + "): " + value);
    }
    return (int) value;
}
Note: In some cases you should use the getLong(TemporalField) method instead of get(TemporalField). The reason is that the int data type is not enough to store the value of some fields, such as ChronoField.PROLEPTIC_MONTH, ChronoField.EPOCH_DAY.
Example:
TemporalAccessor_get_x1.java
package org.o7planning.temporalaccessor.ex;

import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;

public class TemporalAccessor_get_x1 {

    public static void main(String[] args) {
        TemporalAccessor localDate = LocalDate.of(2021, 2, 15);
        System.out.printf("localDate: %s%n%n", localDate); // 2021-02-15T00:00  
        
        if (localDate.isSupported(ChronoField.YEAR)) {
            int year = localDate.get(ChronoField.YEAR);  
            System.out.println("year: " + year); // 2021
        }

        if (localDate.isSupported(ChronoField.DAY_OF_MONTH)) {
            int dayOfMonth = localDate.get(ChronoField.DAY_OF_MONTH);  
            System.out.println("dayOfMonth: " + dayOfMonth); // 15
        }

        if (localDate.isSupported(ChronoField.DAY_OF_YEAR)) {
            int dayOfYear = localDate.get(ChronoField.DAY_OF_YEAR);
            System.out.println("dayOfYear: " + dayOfYear); // 46
        }
    }
}
  • ChronoField
  • TemporalField

6. getLong(TemporalField)

Return the value of the specified field from this TemporalAccessor object as a 64-bit integer.
public long getLong(TemporalField field)
Basically, this method is the same as get(TemporalField). The difference is that it returns long data type. For example, the int data type is not enough to store the value of the ChronoField.EPOCH_DAY field, so you need to use the getLong(Temporal) method.
The following standard fields should be used by the getLong(TemporalField) method instead of the get(TemporalField) method:
  • ChronoField.PROLEPTIC_MONTH
  • ChronoField.EPOCH_DAY
TemporalAccessor_getLong_x1.java
package org.o7planning.temporalaccessor.ex;

import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;

public class TemporalAccessor_getLong_x1 {

    public static void main(String[] args) {
        TemporalAccessor localDate = LocalDate.of(2021, 2, 15);
        System.out.printf("localDate: %s%n%n", localDate); // 2021-02-15T00:00  
        
        if (localDate.isSupported(ChronoField.EPOCH_DAY)) {
            // Using getLong(TemporalField) method:
            long epochDay  = localDate.getLong(ChronoField.EPOCH_DAY);  
            System.out.println("epochDay: " + epochDay); // 18673
        }

        if (localDate.isSupported(ChronoField.EPOCH_DAY)) {
            // Using get(TemporalField) method:
            int epochDay  = localDate.get(ChronoField.EPOCH_DAY); // --> Exception!
            System.out.println("epochDay: " + epochDay);  
        }
    }
}
Output:
localDate: 2021-02-15

epochDay: 18673
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Invalid field 'EpochDay' for get() method, use getLong() instead
    at java.base/java.time.LocalDate.get0(LocalDate.java:699)
    at java.base/java.time.LocalDate.get(LocalDate.java:650)
    at org.o7planning.temporalaccessor.ex.TemporalAccessor_getLong_x1.main(TemporalAccessor_getLong_x1.java:21)
  • ChronoField
  • TemporalField

7. isSupported(TemporalField)

Check if the specified field is supported by this TemporalAccessor.
public boolean isSupported(TemporalField field)
(**) See specific classes for a list of the standard fields it supports.
Example:
  • The LocalDate class represents a date and does not include the time and time zone. It supports standard fields like ChronoField.YEAR, ChronoField.DAY_OF_MONTH,.. but not fields like ChronoField.SECOND_OF_DAY, ChronoField.HOUR_OF_DAY, ...
  • The LocalDateTime class represents a date and time, but does not include the time zone. It supports standard fields like ChronoField.YEAR, ChronoField.DAY_OF_MONTH, ChronoField.SECOND_OF_DAY, ChronoField.HOUR_OF_DAY.. but does not support fields like ChronoField.OFFSET_SECONDS,..
TemporalAccessor_isSupported_ex1.java
TemporalAccessor localDate = LocalDate.of(2021, 2, 15);

System.out.println("Does localDate support: ");
 
System.out.println(" YEAR ? " + localDate.isSupported(ChronoField.YEAR)); // true
System.out.println(" DAY_OF_MONTH ? " + localDate.isSupported(ChronoField.DAY_OF_MONTH)); // true
System.out.println(" SECOND_OF_DAY ? " + localDate.isSupported(ChronoField.SECOND_OF_DAY)); // false
System.out.println(" HOUR_OF_DAY ? " + localDate.isSupported(ChronoField.HOUR_OF_DAY)); // false
System.out.println(" OFFSET_SECONDS ? " + localDate.isSupported(ChronoField.OFFSET_SECONDS)); // false

System.out.println(" ----- ");

TemporalAccessor localDateTime = LocalDateTime.of(2021, 2, 15, 12, 30, 45);
System.out.println("Does localDateTime support: ");

System.out.println(" YEAR ? " + localDateTime.isSupported(ChronoField.YEAR)); // true
System.out.println(" DAY_OF_MONTH ? " + localDateTime.isSupported(ChronoField.DAY_OF_MONTH)); // true
System.out.println(" SECOND_OF_DAY ? " + localDateTime.isSupported(ChronoField.SECOND_OF_DAY)); // true
System.out.println(" HOUR_OF_DAY ? " + localDateTime.isSupported(ChronoField.HOUR_OF_DAY)); // true
System.out.println(" OFFSET_SECONDS ? " + localDate.isSupported(ChronoField.OFFSET_SECONDS)); // false
Output:
Does localDate support:
 YEAR ? true
 DAY_OF_MONTH ? true
 SECOND_OF_DAY ? false
 HOUR_OF_DAY ? false
 OFFSET_SECONDS ? false
 -----
Does localDateTime support:
 YEAR ? true
 DAY_OF_MONTH ? true
 SECOND_OF_DAY ? true
 HOUR_OF_DAY ? true
 OFFSET_SECONDS ? false
  • TemporalField
  • ChronoField