ZetCode

Java TemporalAccessor 接口

最后修改时间:2025 年 4 月 16 日

java.time.temporal.TemporalAccessor 接口提供对时间对象的只读访问。它是 java.time 包中所有日期时间类的基本接口。TemporalAccessor 允许查询时间对象。

TemporalAccessor 定义了用于检查日期时间值的方法。它支持获取字段和查询时间信息。许多类,如 LocalDate 和 ZonedDateTime,都实现了此接口。

TemporalAccessor 接口概述

该接口提供了访问时间信息的方法。关键操作包括检查字段支持和获取字段值。它与 TemporalField 和 TemporalUnit 一起使用,以实现灵活的时间处理。

public interface TemporalAccessor {
    boolean isSupported(TemporalField field);
    long getLong(TemporalField field);
    default int get(TemporalField field);
    default <R> R query(TemporalQuery<R> query);
}

上面的代码展示了 TemporalAccessor 的方法。这些方法允许检查时间对象而不修改它们。该接口构成了 Java 中只读时间操作的基础。

检查支持的字段

isSupported 方法检查时间对象中是否有可用的字段。不同的时间类支持不同的字段。在尝试访问字段值之前,此检查至关重要。

Main.java
package com.zetcode;

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

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.now();
        
        // Check supported fields
        System.out.println("Year supported: " + 
            date.isSupported(ChronoField.YEAR));
        System.out.println("Hour supported: " + 
            date.isSupported(ChronoField.HOUR_OF_DAY));
        System.out.println("Era supported: " + 
            date.isSupported(ChronoField.ERA));
        
        // Alternative check
        System.out.println("Month supported: " + 
            date.isSupported(ChronoField.MONTH_OF_YEAR));
    }
}

此示例演示了如何检查 LocalDate 对象中的字段支持。基于日期的类通常不支持与时间相关的字段。在访问字段之前,请务必验证支持以避免异常。

获取字段值

getLong 方法将字段值作为长整型数字检索。对于较小的范围,get 提供 int 值。这些方法对于不支持的字段会抛出异常。

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();
        
        // Get field values
        long year = dateTime.getLong(ChronoField.YEAR);
        int month = dateTime.get(ChronoField.MONTH_OF_YEAR);
        int day = dateTime.get(ChronoField.DAY_OF_MONTH);
        
        System.out.println("Year: " + year);
        System.out.println("Month: " + month);
        System.out.println("Day: " + day);
        
        // Get time values
        int hour = dateTime.get(ChronoField.HOUR_OF_DAY);
        int minute = dateTime.get(ChronoField.MINUTE_OF_HOUR);
        
        System.out.println("Hour: " + hour);
        System.out.println("Minute: " + minute);
    }
}

此示例展示了如何从 LocalDateTime 检索各种字段值。getLong 方法用于较大的范围,例如年。get 方法适用于较小的范围,例如小时和分钟。

使用 TemporalQuery

query 方法允许复杂的时间查询。它使用 TemporalQuery 实现来提取信息。这提供了比直接字段访问更大的灵活性。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalQueries;

public class Main {

    public static void main(String[] args) {
        
        ZonedDateTime zdt = ZonedDateTime.now();
        
        // Query for local date
        LocalDate date = zdt.query(TemporalQueries.localDate());
        System.out.println("Local date: " + date);
        
        // Query for time zone
        System.out.println("Zone: " + 
            zdt.query(TemporalQueries.zone()));
        
        // Query for precision
        System.out.println("Precision: " + 
            zdt.query(TemporalQueries.precision()));
        
        // Custom query
        String quarter = zdt.query(temporal -> {
            int month = temporal.get(ChronoField.MONTH_OF_YEAR);
            return "Q" + ((month - 1) / 3 + 1);
        });
        System.out.println("Quarter: " + quarter);
    }
}

此示例演示了各种时间查询。 TemporalQueries 中的内置查询提供了常见的操作。自定义查询展示了如何实现业务逻辑,例如季度计算。

使用不同的时间类型

TemporalAccessor 在不同的时间类型之间统一工作。可以使用相同的方法来处理 LocalDate、LocalTime 和其他实现。这提供了对时间信息的一致访问。

Main.java
package com.zetcode;

import java.time.Instant;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.temporal.ChronoField;

public class Main {

    public static void main(String[] args) {
        
        // With LocalTime
        LocalTime time = LocalTime.now();
        System.out.println("Hour: " + time.get(ChronoField.HOUR_OF_DAY));
        
        // With Instant
        Instant instant = Instant.now();
        System.out.println("Epoch second: " + 
            instant.getLong(ChronoField.INSTANT_SECONDS));
        
        // With YearMonth
        YearMonth yearMonth = YearMonth.now();
        System.out.println("Month: " + 
            yearMonth.get(ChronoField.MONTH_OF_YEAR));
        
        // Common interface usage
        printTemporalInfo(time);
        printTemporalInfo(instant);
        printTemporalInfo(yearMonth);
    }
    
    private static void printTemporalInfo(TemporalAccessor temporal) {
        if (temporal.isSupported(ChronoField.YEAR)) {
            System.out.println("Year: " + 
                temporal.getLong(ChronoField.YEAR));
        }
    }
}

此示例展示了 TemporalAccessor 与不同的时间类型一起工作。 printTemporalInfo 方法演示了多态行为。请注意在访问年份值之前进行字段支持检查。

提取部分信息

TemporalAccessor 可以从时间对象中提取部分信息。当只需要特定字段时,这很有用。该接口提供了对时间数据的灵活访问。

Main.java
package com.zetcode;

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

public class Main {

    public static void main(String[] args) {
        
        LocalDateTime ldt = LocalDateTime.now();
        
        // Extract date part
        System.out.println("Date: " + 
            ldt.get(ChronoField.YEAR) + "-" +
            ldt.get(ChronoField.MONTH_OF_YEAR) + "-" +
            ldt.get(ChronoField.DAY_OF_MONTH));
        
        // Extract time part
        System.out.println("Time: " + 
            ldt.get(ChronoField.HOUR_OF_DAY) + ":" +
            ldt.get(ChronoField.MINUTE_OF_HOUR) + ":" +
            ldt.get(ChronoField.SECOND_OF_MINUTE));
        
        // Extract day of week
        System.out.println("Day of week: " + 
            ldt.get(ChronoField.DAY_OF_WEEK));
        
        // Extract week of year
        System.out.println("Week of year: " + 
            ldt.get(ChronoField.ALIGNED_WEEK_OF_YEAR));
    }
}

此示例演示了如何从 LocalDateTime 提取特定字段。代码展示了如何构建自定义字符串表示形式。可以独立访问各种日期和时间组件。

处理不支持的字段

使用 TemporalAccessor 时,某些字段可能不受支持。适当的错误处理至关重要。isSupported 检查应先于字段访问。

Main.java
package com.zetcode;

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

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.now();
        
        try {
            // Attempt to access unsupported field
            int hour = date.get(ChronoField.HOUR_OF_DAY);
            System.out.println("Hour: " + hour);
        } catch (UnsupportedTemporalTypeException e) {
            System.out.println("Error: " + e.getMessage());
        }
        
        // Safe field access
        if (date.isSupported(ChronoField.DAY_OF_YEAR)) {
            System.out.println("Day of year: " + 
                date.get(ChronoField.DAY_OF_YEAR));
        } else {
            System.out.println("Day of year not supported");
        }
    }
}

此示例展示了如何正确处理不支持的字段。第一次尝试对不支持的时间字段抛出异常。第二种方法在访问之前安全地检查支持情况。

来源

Java TemporalAccessor 接口文档

在本文中,我们介绍了 Java TemporalAccessor 接口的基本方法和特性。理解这些概念对于在现代 Java 应用程序中处理时间对象至关重要。

作者

我的名字是 Jan Bodnar,是一位经验丰富的程序员,在这一领域拥有多年经验。我从 2007 年开始撰写编程文章,至今已撰写了 1400 多篇文章和 8 本电子书。凭借超过 8 年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程