432. Java 日期时间 API - 时间工具 TemporalQuery 详解

432. Java 日期时间 API - 时间工具 TemporalQuery 详解

大家好 👋,今天我们要聊的是 TemporalQuery ------ 它的作用可以简单理解为: 👉 "从时间对象里问问题,提取信息"。

比如:

  • "这个日期的精度是到天?还是到纳秒?"
  • "这一天是不是家人的生日?"
  • "这一天是不是在我们的假期里?"

听起来就像给日期做"问答",对吧?😎


1. 什么是 TemporalQuery?

  • 接口 :位于 java.time.temporal 包
  • 作用 :用来从 TemporalAccessor(时间对象)中获取特定信息
  • 常见用法 :通过 date.query(query) 的方式来提问

2. 系统自带的查询器(Predefined Queries)

Java 提供了 TemporalQueries 工具类,其中有一些常用的查询器。

示例:查询不同时间对象的"最小精度"

java 复制代码
import java.time.*;
import java.time.temporal.*;

public class TemporalQueryDemo {
    public static void main(String[] args) {
        TemporalQuery<TemporalUnit> query = TemporalQueries.precision();

        System.out.printf("LocalDate precision is %s%n",
                          LocalDate.now().query(query));
        System.out.printf("LocalDateTime precision is %s%n",
                          LocalDateTime.now().query(query));
        System.out.printf("Year precision is %s%n",
                          Year.now().query(query));
        System.out.printf("YearMonth precision is %s%n",
                          YearMonth.now().query(query));
        System.out.printf("Instant precision is %s%n",
                          Instant.now().query(query));
    }
}

输出结果:

java 复制代码
LocalDate precision is Days
LocalDateTime precision is Nanos
Year precision is Years
YearMonth precision is Months
Instant precision is Nanos

👉 从结果可以看出:

  • LocalDate → 精确到 天
  • LocalDateTime 、Instant → 精确到 纳秒
  • Year → 精确到 年
  • YearMonth → 精确到 月

这对我们理解不同时间类的粒度非常有帮助。


3. 自定义查询器(Custom Queries)

有时候我们需要更贴合业务的查询,比如:

  • 判断某天是不是家人度假日
  • 判断某天是不是家人生日

这时我们可以写 自定义查询器。


3.1 假期查询器 ------ FamilyVacations 🌴

我们写一个 TemporalQuery<Boolean> 来判断某个日期是否在家庭假期范围内:

java 复制代码
import java.time.*;
import java.time.temporal.*;

public class FamilyVacations implements TemporalQuery<Boolean> {
    @Override
    public Boolean queryFrom(TemporalAccessor date) {
        int month = date.get(ChronoField.MONTH_OF_YEAR);
        int day = date.get(ChronoField.DAY_OF_MONTH);

        // 例:4 月 3-8 号是去迪士尼
        if ((month == Month.APRIL.getValue()) && (day >= 3 && day <= 8))
            return true;

        // 例:8 月 8-14 号是家庭聚会
        if ((month == Month.AUGUST.getValue()) && (day >= 8 && day <= 14))
            return true;

        return false;
    }
}

使用方式:

java 复制代码
LocalDate date = LocalDate.of(2025, 4, 5);
boolean isVacation = date.query(new FamilyVacations());
System.out.println(date + " 是假期吗? " + isVacation);

👉 输出:

java 复制代码
2025-04-05 是假期吗? true

3.2 生日查询器 ------ FamilyBirthdays 🎂

有时候我们只关心 某天是不是某人的生日。

这时可以用 静态方法 + Lambda 表达式 来实现,代码更简洁。

java 复制代码
import java.time.*;
import java.time.temporal.*;

public class FamilyBirthdays {
    public static Boolean isFamilyBirthday(TemporalAccessor date) {
        int month = date.get(ChronoField.MONTH_OF_YEAR);
        int day = date.get(ChronoField.DAY_OF_MONTH);

        if (month == Month.APRIL.getValue() && day == 3) return true;   // Angie
        if (month == Month.JUNE.getValue() && day == 18) return true;   // Sue
        if (month == Month.MAY.getValue() && day == 29) return true;    // Joe

        return false;
    }
}

使用方式:

java 复制代码
LocalDate date = LocalDate.of(2025, 6, 18);

boolean isVacation = date.query(new FamilyVacations());
boolean isBirthday = date.query(FamilyBirthdays::isFamilyBirthday);

if (isVacation || isBirthday) {
    System.out.printf("%s 是重要的日子!%n", date);
} else {
    System.out.printf("%s 是普通的一天。%n", date);
}

👉 输出:

java 复制代码
2025-06-18 是重要的日子!

4. 总结 🎓

  • TemporalQuery = "问时间对象问题"的接口
  • 系统预定义查询器:精度(precision)、时区(zone)、偏移量(offset)等
  • 自定义查询器:可以实现业务逻辑(假期、生日、纪念日...)
  • 调用方式统一 :date.query(query) 或者 date.query(ClassName::methodName)
相关推荐
就像楞次定律8 小时前
【Linux 学习记之二】C++ 构建体系与底层链接机制的深度透视(1)
linux·后端
学到老活到老8 小时前
第 22 集:Filter、Interceptor、AOP 都能拦截,为什么不能互换?
java·后端·spring
尘世中一位迷途小书童8 小时前
和 AI 打交道会撞见的一整串词:从大模型到 Agent、RAG、MCP、Skill,一次串清
前端·人工智能
lusklusklusk8 小时前
Python 全局变量与局部变量区别——global 关键字、__main__ 块与作用域示例
开发语言·前端·python
郭小李8 小时前
spring 中的 @EnableWebMvc注解和WebMvcConfigurer接口
java·后端·spring
产品经理爱开发8 小时前
AxureShow(艾可秀)国内通用的html托管
前端·人工智能·html·ai编程
jktantan8 小时前
前端也需要事务:Vue Router 乐观更新、回滚与“过期事务”
前端·javascript·vue.js
卷无止境8 小时前
Skill 的安全边界在哪里:风险来源、验证思路与用户可用的防线
后端·python
怕浪猫8 小时前
K3.1 直追 Astra,先补 13%
前端·javascript·面试
天若有情6738 小时前
【前端趣味项目】把防抖玩出新花样!一个带隐藏后门的毫秒级“读秒挑战”
前端·javascript·html·防抖·外挂·趣味demo·读秒挑战