ZetCode

Java TemporalQuery 接口

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

java.time.temporal.TemporalQuery 接口提供了一种查询时间对象以获取信息的方法。 它表示一个从时间对象(如 LocalDate 或 ZonedDateTime)中提取信息的函数。

TemporalQuery 是一个函数式接口,具有单个抽象方法 queryFrom。 它在整个 Java 时间 API 中用于灵活的时间查询。 该接口实现了类型安全的时间操作。

TemporalQuery 接口概述

TemporalQuery 接口定义了一个方法,该方法接受一个 TemporalAccessor 并返回一个结果。 结果类型由查询实现决定。 查询可以提取任何时间信息。

@FunctionalInterface
public interface TemporalQuery<R> {
    R queryFrom(TemporalAccessor temporal);
}

上面的代码展示了 TemporalQuery 接口的简单结构。 泛型类型参数 R 指定返回类型。 实现可以查询时间对象的任何方面。

基本 TemporalQuery 示例

此示例演示了创建一个简单的 TemporalQuery,它从时间对象中提取星期几。 查询实现为一个 lambda 表达式。

Main.java
package com.zetcode;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalQuery;

public class Main {

    public static void main(String[] args) {
        
        TemporalQuery<DayOfWeek> dayOfWeekQuery = temporal -> 
            DayOfWeek.from(temporal);
            
        LocalDate date = LocalDate.of(2025, 4, 16);
        DayOfWeek day = date.query(dayOfWeekQuery);
        
        System.out.println("Day of week: " + day);
    }
}

此示例创建一个查询,从任何支持此信息的时间对象中提取星期几。 query 方法将查询应用于时间对象。 结果将打印到控制台。

查询特定信息

此示例展示了如何创建一个查询来检查日期是否为周末。 查询返回一个布尔值,指示日期是否为星期六或星期日。

Main.java
package com.zetcode;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalQuery;

public class Main {

    public static void main(String[] args) {
        
        TemporalQuery<Boolean> isWeekendQuery = temporal -> {
            DayOfWeek day = DayOfWeek.from(temporal);
            return day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY;
        };
        
        LocalDate weekday = LocalDate.of(2025, 4, 16);
        LocalDate weekend = LocalDate.of(2025, 4, 19);
        
        System.out.println("Is weekday weekend? " + weekday.query(isWeekendQuery));
        System.out.println("Is weekend day weekend? " + weekend.query(isWeekendQuery));
    }
}

该示例定义了一个查询,用于检查周末日期。 查询提取星期几,如果它是星期六或星期日,则返回 true。 测试了两个日期以演示查询的功能。

使用预定义的 TemporalQueries

Java 时间 API 在 TemporalQueries 类中提供了几个预定义的查询。 这些查询可以直接使用,无需创建自定义实现。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
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 local time
        LocalTime time = zdt.query(TemporalQueries.localTime());
        System.out.println("Local time: " + time);
        
        // Query for zone
        ZoneId zone = zdt.query(TemporalQueries.zone());
        System.out.println("Zone: " + zone);
        
        // Query for precision
        System.out.println("Precision: " + zdt.query(TemporalQueries.precision()));
    }
}

此示例演示了如何使用来自 TemporalQueries 的预定义查询。 查询提取 ZonedDateTime 对象的不同方面。 每个查询返回特定类型的时间信息。

链接 TemporalQueries

Temporal 查询可以链接在一起以执行复杂的时间操作。 此示例展示了如何组合多个查询以提取特定信息。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalQuery;

public class Main {

    public static void main(String[] args) {
        
        TemporalQuery<Boolean> isSummerQuery = temporal -> {
            LocalDate date = LocalDate.from(temporal);
            return date.getMonth() == Month.JUNE 
                || date.getMonth() == Month.JULY 
                || date.getMonth() == Month.AUGUST;
        };
        
        TemporalQuery<Boolean> isWeekendInSummerQuery = temporal -> {
            boolean isSummer = temporal.query(isSummerQuery);
            boolean isWeekend = temporal.query(t -> {
                var day = java.time.DayOfWeek.from(t);
                return day == java.time.DayOfWeek.SATURDAY 
                    || day == java.time.DayOfWeek.SUNDAY;
            });
            return isSummer &&  isWeekend;
        };
        
        LocalDate summerWeekend = LocalDate.of(2025, 7, 19);
        LocalDate winterWeekend = LocalDate.of(2025, 1, 18);
        
        System.out.println("Is summer weekend? " + 
            summerWeekend.query(isWeekendInSummerQuery));
        System.out.println("Is winter weekend? " + 
            winterWeekend.query(isWeekendInSummerQuery));
    }
}

此示例创建一个复杂查询,用于检查日期是否是周末并且在夏季。 查询组合了两个更简单的查询来实现此目的。 结果演示了如何组合查询以获得更复杂的条件。

查询自定义业务逻辑

Temporal 查询可以封装有关日期和时间的业务规则。 此示例显示了一个查询,该查询检查日期时间是否在营业时间内。

Main.java
package com.zetcode;

import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalQuery;

public class Main {

    public static void main(String[] args) {
        
        TemporalQuery<Boolean> isBusinessHoursQuery = temporal -> {
            ZonedDateTime zdt = ZonedDateTime.from(temporal);
            LocalTime time = zdt.toLocalTime();
            DayOfWeek day = zdt.getDayOfWeek();
            
            // Business hours: 9AM-5PM, Monday-Friday
            return !(day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY)
                &&  time.isAfter(LocalTime.of(8, 59))
                &&  time.isBefore(LocalTime.of(17, 1));
        };
        
        ZonedDateTime businessTime = ZonedDateTime.of(
            2025, 4, 16, 10, 30, 0, 0, ZoneId.of("America/New_York"));
        ZonedDateTime nonBusinessTime = ZonedDateTime.of(
            2025, 4, 19, 11, 0, 0, 0, ZoneId.of("America/New_York"));
        
        System.out.println("Is business time? " + 
            businessTime.query(isBusinessHoursQuery));
        System.out.println("Is non-business time? " + 
            nonBusinessTime.query(isBusinessHoursQuery));
    }
}

此示例在时间查询中实现了有关工作时间的业务逻辑。 查询检查星期几和一天中的时间。 结果演示了查询如何根据定义的规则正确识别营业时间。

使用方法引用作为 TemporalQueries

方法引用可以用作 TemporalQuery 的简洁实现。 此示例展示了如何使用现有方法作为时间对象的查询。

Main.java
package com.zetcode;

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

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 4, 16);
        
        // Using method references as queries
        Month month = date.query(LocalDate::getMonth);
        int year = date.query(LocalDate::getYear);
        int day = date.query(LocalDate::getDayOfMonth);
        
        System.out.println("Year: " + year);
        System.out.println("Month: " + month);
        System.out.println("Day: " + day);
        
        // Alternative using predefined queries
        System.out.println("Month (predefined): " + 
            date.query(TemporalQueries.localDate()).getMonth());
    }
}

此示例演示了如何使用方法引用作为时间查询。 query 方法接受与 TemporalQuery 函数式接口匹配的方法引用。 该示例显示了直接方法引用和预定义查询进行比较。

将 TemporalQuery 与 TemporalAdjuster 结合使用

Temporal 查询可以与调整器结合使用,以创建强大的时间操作。 此示例查找给定日期后的下一个工作日。

Main.java
package com.zetcode;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalQuery;

public class Main {

    public static void main(String[] args) {
        
        TemporalQuery<Boolean> isBusinessDayQuery = temporal -> {
            DayOfWeek day = DayOfWeek.from(temporal);
            return day != DayOfWeek.SATURDAY &&  day != DayOfWeek.SUNDAY;
        };
        
        TemporalAdjuster nextBusinessDay = temporal -> {
            LocalDate date = LocalDate.from(temporal);
            do {
                date = date.plusDays(1);
            } while (!date.query(isBusinessDayQuery));
            return date;
        };
        
        LocalDate friday = LocalDate.of(2025, 4, 18);
        LocalDate nextBusiness = friday.with(nextBusinessDay);
        
        System.out.println("Friday: " + friday);
        System.out.println("Next business day: " + nextBusiness);
    }
}

此示例将时间查询与时间调整器相结合。 查询标识工作日,调整器查找下一个工作日。 结果演示了跳过周末以找到下一个工作日。

来源

Java TemporalQuery 接口文档

在本文中,我们介绍了 Java TemporalQuery 接口的基本方法和功能。 了解这些概念对于现代 Java 应用程序中的灵活时间操作至关重要。

作者

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

列出所有Java教程