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)