文档

Java™ 教程
隐藏目录
Temporal Query
跟踪:日期 时间
教训:标准日历
部分:时间包

时间查询

一个TemporalQuery可以用来从基于时间的对象中检索信息。

预定义查询

TemporalQueries类(注意复数形式)提供了几个预定义的查询,包括在应用程序无法确定基于时间的对象的类型时有用的方法。与调整器一样,预定义查询被定义为静态方法,并且设计用于与static import语句一起使用。

例如,precision查询返回特定基于时间的对象可以返回的最小ChronoUnit。以下示例在几种类型的基于时间的对象上使用precision查询:

TemporalQuery<TemporalUnit> query = TemporalQueries.precision();
System.out.printf("LocalDate的精度为%s%n",
                  LocalDate.now().query(query));
System.out.printf("LocalDateTime的精度为%s%n",
                  LocalDateTime.now().query(query));
System.out.printf("Year的精度为%s%n",
                  Year.now().query(query));
System.out.printf("YearMonth的精度为%s%n",
                  YearMonth.now().query(query));
System.out.printf("Instant的精度为%s%n",
                  Instant.now().query(query));

输出结果如下:

LocalDate的精度为Days
LocalDateTime的精度为Nanos
Year的精度为Years
YearMonth的精度为Months
Instant的精度为Nanos

自定义查询

您还可以创建自己的自定义查询。一种方法是创建一个实现TemporalQuery接口并具有queryFrom(TemporalAccessor)方法的类。示例CheckDate实现了两个自定义查询。第一个自定义查询可以在FamilyVacations类中找到,该类实现了TemporalQuery接口。queryFrom方法将传入的日期与计划的假期日期进行比较,如果日期在这些日期范围内,则返回TRUE

// 如果传入的日期是家庭度假的日期之一,则返回true。因为查询只比较月份和日期,即使Temporal类型不同,检查也会成功。
public Boolean queryFrom(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) && (day <= 8)))
        return Boolean.TRUE;

    // 史密斯家族重聚在萨各托克湖
    if ((month == Month.AUGUST.getValue()) && ((day >= 8) && (day <= 14)))
        return Boolean.TRUE;

    return Boolean.FALSE;
}

第二个自定义查询实现在FamilyBirthdays类中。该类提供了一个isFamilyBirthday方法,用于将传入的日期与几个生日进行比较,并返回TRUE如果有匹配。

// 如果传入的日期与家庭生日之一相同,则返回true。因为查询只比较月份和日期,即使Temporal类型不同,检查也会成功。
public static Boolean isFamilyBirthday(TemporalAccessor date) {
    int month = date.get(ChronoField.MONTH_OF_YEAR);
    int day   = date.get(ChronoField.DAY_OF_MONTH);

    // 安吉的生日是4月3日。
    if ((month == Month.APRIL.getValue()) && (day == 3))
        return Boolean.TRUE;

    // 苏的生日是6月18日。
    if ((month == Month.JUNE.getValue()) && (day == 18))
        return Boolean.TRUE;

    // 乔的生日是5月29日。
    if ((month == Month.MAY.getValue()) && (day == 29))
        return Boolean.TRUE;

    return Boolean.FALSE;
}

FamilyBirthday类没有实现TemporalQuery接口,并且可以作为lambda表达式的一部分使用。以下代码来自CheckDate示例,展示了如何调用这两个自定义查询。

// 不使用lambda表达式调用查询。
Boolean isFamilyVacation = date.query(new FamilyVacations());

// 使用lambda表达式调用查询。
Boolean isFamilyBirthday = date.query(FamilyBirthdays::isFamilyBirthday);

if (isFamilyVacation.booleanValue() || isFamilyBirthday.booleanValue())
    System.out.printf("%s是一个重要的日期!%n", date);
else
    System.out.printf("%s不是一个重要的日期。%n", date);

上一页: 时间调整器
下一页: 时期和持续时间