ZetCode

Java TemporalUnit Interface

Last modified: April 16, 2025

The java.time.temporal.TemporalUnit interface represents a unit of time. It is part of the Java Date and Time API introduced in Java 8. TemporalUnit defines how a unit of time is measured and manipulated.

TemporalUnit is implemented by ChronoUnit enum which provides standard units like seconds, minutes, hours, days, etc. The interface allows custom time units to be created. It works with temporal objects like Instant and LocalDateTime.

TemporalUnit Interface Overview

The TemporalUnit interface defines methods to query and manipulate temporal objects. Key operations include checking duration, adding to temporals, and estimating length. The interface enables flexible time calculations.

public interface TemporalUnit {
    Duration getDuration();
    boolean isDurationEstimated();
    boolean isDateBased();
    boolean isTimeBased();
    boolean isSupportedBy(Temporal temporal);
    <R extends Temporal> R addTo(R temporal, long amount);
    long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive);
    String toString();
}

The code above shows key methods of TemporalUnit. These methods allow querying unit characteristics and performing temporal arithmetic. The interface is fundamental for time-based calculations in Java.

Using ChronoUnit Constants

ChronoUnit enum provides standard implementations of TemporalUnit. These constants represent common time units from nanoseconds to centuries. They are the most common way to use TemporalUnit.

Main.java
package com.zetcode;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDateTime now = LocalDateTime.now();
        
        // Add 5 hours
        LocalDateTime later = now.plus(5, ChronoUnit.HOURS);
        System.out.println("5 hours later: " + later);
        
        // Subtract 3 days
        LocalDateTime earlier = now.minus(3, ChronoUnit.DAYS);
        System.out.println("3 days earlier: " + earlier);
        
        // Check if time-based
        System.out.println("Is DAYS time-based? " + ChronoUnit.DAYS.isTimeBased());
        
        // Check if date-based
        System.out.println("Is HOURS date-based? " + ChronoUnit.HOURS.isDateBased());
    }
}

This example demonstrates using ChronoUnit constants with LocalDateTime. The plus and minus methods accept TemporalUnit parameters. ChronoUnit provides both time-based and date-based units.

Checking Unit Characteristics

TemporalUnit provides methods to check unit properties. These include whether a unit is time-based, date-based, or has an estimated duration. This information is useful for validation and conditional logic.

Main.java
package com.zetcode;

import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        // Check unit characteristics
        System.out.println("NANOS duration: " + ChronoUnit.NANOS.getDuration());
        System.out.println("Is YEARS estimated? " + ChronoUnit.YEARS.isDurationEstimated());
        
        // Time-based vs date-based
        System.out.println("SECONDS isTimeBased: " + ChronoUnit.SECONDS.isTimeBased());
        System.out.println("MONTHS isDateBased: " + ChronoUnit.MONTHS.isDateBased());
        
        // Mixed units
        System.out.println("WEEKS isTimeBased: " + ChronoUnit.WEEKS.isTimeBased());
        System.out.println("WEEKS isDateBased: " + ChronoUnit.WEEKS.isDateBased());
    }
}

This example shows how to query TemporalUnit characteristics. Note that some units like WEEKS are neither time-based nor date-based. The duration of date-based units may be estimated due to variable month lengths.

Calculating Time Between Dates

The between method calculates time between two temporal objects in a specific unit. This is useful for measuring durations in different units. The calculation respects calendar rules where applicable.

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date1 = LocalDate.of(2025, 1, 1);
        LocalDate date2 = LocalDate.of(2025, 6, 15);
        
        // Calculate difference in days
        long daysBetween = ChronoUnit.DAYS.between(date1, date2);
        System.out.println("Days between: " + daysBetween);
        
        // Calculate difference in months
        long monthsBetween = ChronoUnit.MONTHS.between(date1, date2);
        System.out.println("Months between: " + monthsBetween);
        
        LocalTime time1 = LocalTime.of(8, 30);
        LocalTime time2 = LocalTime.of(14, 45);
        
        // Calculate difference in hours
        double hoursBetween = ChronoUnit.HOURS.between(time1, time2);
        System.out.println("Hours between: " + hoursBetween);
    }
}

This example demonstrates calculating time differences using TemporalUnit. The between method returns the amount in the specified unit. For date-based units, the calculation considers calendar rules.

Creating Custom TemporalUnit

While ChronoUnit covers most needs, you can implement TemporalUnit for custom time units. This requires implementing all interface methods. The example shows a simple work week unit.

Main.java
package com.zetcode;

import java.time.Duration;
import java.time.LocalDate;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalUnit;
import java.util.List;

public class Main {

    static class WorkWeekUnit implements TemporalUnit {
        
        @Override
        public Duration getDuration() {
            return Duration.ofDays(5);
        }
        
        @Override
        public boolean isDurationEstimated() {
            return false;
        }
        
        @Override
        public boolean isDateBased() {
            return true;
        }
        
        @Override
        public boolean isTimeBased() {
            return false;
        }
        
        @Override
        public boolean isSupportedBy(Temporal temporal) {
            return temporal.isSupported(ChronoUnit.DAYS);
        }
        
        @Override
        public Temporal addTo(Temporal temporal, long amount) {
            return temporal.plus(amount * 5, ChronoUnit.DAYS);
        }
        
        @Override
        public long between(Temporal temporal1, Temporal temporal2) {
            return ChronoUnit.DAYS.between(temporal1, temporal2) / 5;
        }
        
        @Override
        public String toString() {
            return "WorkWeek";
        }
    }

    public static void main(String[] args) {
        
        WorkWeekUnit workWeek = new WorkWeekUnit();
        LocalDate startDate = LocalDate.of(2025, 1, 1);
        
        // Add 2 work weeks
        LocalDate endDate = (LocalDate) workWeek.addTo(startDate, 2);
        System.out.println("After 2 work weeks: " + endDate);
        
        // Calculate work weeks between
        long weeks = workWeek.between(startDate, endDate);
        System.out.println("Work weeks between: " + weeks);
    }
}

This example shows a custom WorkWeekUnit implementation. The unit considers 5 days as one work week. All TemporalUnit methods are implemented to support this custom time measurement.

Combining TemporalUnit with Duration

TemporalUnit works well with Duration for precise time calculations. Duration can be created from TemporalUnit's getDuration method. This enables flexible time-based operations.

Main.java
package com.zetcode;

import java.time.Duration;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        // Get duration of different units
        Duration hourDuration = ChronoUnit.HOURS.getDuration();
        System.out.println("Duration of HOURS: " + hourDuration);
        
        Duration dayDuration = ChronoUnit.DAYS.getDuration();
        System.out.println("Duration of DAYS: " + dayDuration);
        
        // Use with LocalTime
        LocalTime time = LocalTime.of(9, 0);
        LocalTime newTime = time.plus(hourDuration.multipliedBy(3));
        System.out.println("Time after 3 hours: " + newTime);
        
        // Compare durations
        System.out.println("Is HOURS shorter than DAYS? " + 
            (hourDuration.compareTo(dayDuration) < 0));
    }
}

This example demonstrates the relationship between TemporalUnit and Duration. The getDuration method provides the standard duration of a unit. Durations can be used directly in temporal calculations.

Validating Unit Support

Not all temporal objects support all units. The isSupportedBy method checks if a unit can be used with a specific temporal object. This prevents unsupported operation exceptions.

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.now();
        
        // Check date support
        System.out.println("MONTHS supported by date: " + 
            ChronoUnit.MONTHS.isSupportedBy(date));
        System.out.println("HOURS supported by date: " + 
            ChronoUnit.HOURS.isSupportedBy(date));
        
        // Check time support
        System.out.println("SECONDS supported by time: " + 
            ChronoUnit.SECONDS.isSupportedBy(time));
        System.out.println("DAYS supported by time: " + 
            ChronoUnit.DAYS.isSupportedBy(time));
        
        // Try to use unsupported unit
        if (ChronoUnit.YEARS.isSupportedBy(time)) {
            time = time.plus(1, ChronoUnit.YEARS);
        } else {
            System.out.println("Cannot add YEARS to LocalTime");
        }
    }
}

This example shows how to check unit support before performing operations. LocalDate supports date-based units while LocalTime supports time-based units. The check prevents attempts to use incompatible units.

Source

Java TemporalUnit Interface Documentation

In this article, we've covered the essential methods and features of the Java TemporalUnit interface. Understanding these concepts is crucial for flexible time handling 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.