ZetCode

Java Temporal Interface

Last modified: April 16, 2025

The java.time.temporal.Temporal interface is a framework-level interface that represents date-time objects. It provides access to date-time fields and allows date-time arithmetic. Classes like LocalDate and ZonedDateTime implement this interface.

Temporal defines operations for querying and manipulating temporal objects. It supports adding or subtracting time units, comparing dates, and accessing temporal fields. The interface enables polymorphic handling of different date-time types.

Temporal Interface Overview

The Temporal interface provides methods for temporal arithmetic and field access. Key operations include adding/subtracting time, querying fields, and adjusting values. It works with TemporalUnit and TemporalField for flexible operations.

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);
}

The code above shows key methods of the Temporal interface. These methods enable manipulation of temporal objects while maintaining immutability. Implementing classes provide concrete behavior for these operations.

Basic Temporal Operations

This example demonstrates basic operations available through the Temporal interface. We'll use LocalDate which implements Temporal to show common methods. The operations include adding time and querying fields.

Main.java
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);
    }
}

This example shows basic Temporal operations using LocalDate. The plus and minus methods return new Temporal objects. The isSupported method checks if a time unit can be used with the temporal object.

Field Adjustments with Temporal

The Temporal interface allows modifying specific fields of date-time objects. This is done using the with method which returns a new adjusted object. Field adjustments are precise and handle edge cases automatically.

Main.java
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);
    }
}

This example demonstrates field adjustments using the Temporal interface. Each with operation returns a new Temporal object. Multiple adjustments can be chained together to create complex transformations.

Calculating Time Between Temporals

The until method calculates time between two temporal objects in specified units. This is useful for determining durations between dates or times. The method handles different temporal types automatically.

Main.java
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);
    }
}

This example shows how to calculate time between temporal objects. The until method works with different temporal types and units. Note that calculations are exact and respect calendar rules.

Temporal with TemporalAdjuster

Temporal objects can work with TemporalAdjusters for complex date adjustments. Adjusters provide pre-built operations like "next Tuesday" or "last day of month". This demonstrates the flexibility of the Temporal interface.

Main.java
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);
    }
}

This example demonstrates using TemporalAdjusters with Temporal objects. The adjusters provide common date operations through a functional interface. Custom adjusters can also be created using lambda expressions.

Working with TemporalQueries

Temporal objects support queries for extracting information. The query method allows flexible extraction of data from temporal objects. This is useful for generic date-time processing code.

Main.java
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);
    }
}

This example shows how to query temporal objects for information. Built-in queries are available through TemporalQueries, and custom queries can be created. The query method enables polymorphic handling of different temporal types.

Combining Temporal Operations

This example demonstrates combining multiple Temporal operations for complex date-time calculations. We'll chain operations to create a business logic scenario involving date calculations.

Main.java
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);
    }
}

This example combines multiple Temporal operations to model a project timeline. We use plus operations, adjusters, and duration calculations. Note the casting needed when specific methods from LocalDate are required.

Source

Java Temporal Interface Documentation

In this article, we've covered the essential methods and features of the Java Temporal interface. Understanding these concepts is crucial for working with date and time in modern Java applications.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.