devstory

Le Tutoriel de Java TemporalQuery

  1. TemporalQuery
  2. Ex: AllLeapYearsInSameDecadeQuery
  3. Ex: AllMondaysInSameMonthQuery
  4. Ex: AllZoneIdsSameOffsetQuery
  5. TemporalQueries

1. TemporalQuery

L'interface TemporalQuery est un outil permettant d'interroger un objet TemporalAccessor pour extraire des informations. En règle générale, TemporalQuery existe pour externaliser les informations d'interrogation de l'objet TemporalAccessor au lieu d'extraire les informations directement.
@FunctionalInterface
public interface TemporalQuery<R> {
    R queryFrom(TemporalAccessor temporal);
}
Par exemple : On écrit la classe HourMinuteQuery pour extraire les informations relatives aux heures et aux minutes sous la forme d'une chaîne "HH:mm" à partir des objets TemporalAccessor.
TemporalAccessor
Example
Using HourMinuteQuery
LocalDateTime
2020-11-25 13:30:45
13:30
ZonedDateTime
2020-11-25 15:30:45+06:00[Asia/Bishkek]
15:30
LocalTime
21:45:45
21:45
HourMinuteQuery.java
package org.o7planning.temporalquery.ex;

import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;

public class HourMinuteQuery implements TemporalQuery<String> {
    @Override
    public String queryFrom(TemporalAccessor temporal) {
        if (temporal.isSupported(ChronoField.HOUR_OF_DAY) //
                && temporal.isSupported(ChronoField.MINUTE_OF_HOUR)) {
            int hour = temporal.get(ChronoField.HOUR_OF_DAY);
            int minute = temporal.get(ChronoField.MINUTE_OF_HOUR);
            return hour + ":" + minute;
        }
        return null;
    }
}
Utiliser HourMinuteQuery:
HourMinuteQuery_ex1.java
package org.o7planning.temporalquery.ex;

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class HourMinuteQuery_ex1  {
    public static void main(String[] args) {
        // TemporalAccessor object:
        ZonedDateTime parisNow = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
        
        System.out.printf("Paris now is: %s%n", parisNow);
        
        HourMinuteQuery query = new HourMinuteQuery();
        
        String info = query.queryFrom(parisNow);
        System.out.println("Info: " + info);
    }
}
Output:
Paris now is: 2021-07-05T19:17:54.978689+02:00[Europe/Paris]
Info: 19:17
Il existe deux manières d'interroger un objet TemporalAccessor, dont la deuxième approche est recommandée.
// These two lines are equivalent, but the second approach is recommended
information = thisQuery.queryFrom(temporalAccessor);  // (1)
information = temporalAccessor.query(thisQuery);          // (2)

2. Ex: AllLeapYearsInSameDecadeQuery

Créer une TemporalQuery pour chercher toutes les années bissextiles dans une même décennie avec un objet TemporalAccessor.
AllLeapYearsInSameDecadeQuery.java
package org.o7planning.temporalquery.ex;

import java.time.DateTimeException;
import java.time.chrono.ChronoLocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;
import java.util.ArrayList;
import java.util.List;

// Return all leap years in the same Decade with a TemporalAccessor.
public class AllLeapYearsInSameDecadeQuery implements TemporalQuery<List<Integer>> {

    @Override
    public List<Integer> queryFrom(TemporalAccessor temporal) {
        if (!(temporal instanceof ChronoLocalDate)) {
            throw new DateTimeException("Only ChronoLocalDate is supported");
        }
        List<Integer> leapYears = new ArrayList<>();

        ChronoLocalDate localDate = (ChronoLocalDate) temporal;

        int year = localDate.get(ChronoField.YEAR);
        int firstYearInSameDecade = year - (year % 10);
        
        for (int i = 0; i < 10; i++) {
            int y = firstYearInSameDecade + i;
            ChronoLocalDate newLocalDate = localDate.with(ChronoField.YEAR, y);
            if (newLocalDate.isLeapYear()) {
                leapYears.add(newLocalDate.get(ChronoField.YEAR));
            }
        }
        return leapYears;
    }
}
AllLeapYearsInSameDecadeQuery_ex1.java
LocalDate today = LocalDate.now();
System.out.println("Today is: " + today);
System.out.println("Year: " + today.getYear());

System.out.printf("Leap years in the same decade with %d:%n%n", today.getYear());

AllLeapYearsInSameDecadeQuery query = new AllLeapYearsInSameDecadeQuery();

// Return leap years in the same decade with today.
List<Integer> leapYears = query.queryFrom(today);
for(Integer leapYear: leapYears)  {
    System.out.println("Leap year: " + leapYear);
}
Output:
Today is: 2021-07-05
Year: 2021
Leap years in the same decade with 2021:

Leap year: 2020
Leap year: 2024
Leap year: 2028

3. Ex: AllMondaysInSameMonthQuery

Créer une TemporalQuery pour chercher tous les Lundis (Mondays) dans un même mois avec un objet TemporalAccessor.
AllMondaysInSameMonthQuery.java
package org.o7planning.temporalquery.ex;

import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;
import java.time.temporal.ValueRange;
import java.util.ArrayList;
import java.util.List;

public class AllMondaysInSameMonthQuery implements TemporalQuery<List<LocalDate>>{

    @Override
    public List<LocalDate> queryFrom(TemporalAccessor temporal) {
        if(!(temporal instanceof LocalDate))  {
            throw new DateTimeException("Only LocalDate is supported");
        }
        LocalDate localDate = (LocalDate) temporal;
        List<LocalDate> retList= new ArrayList<LocalDate>();
        
        ValueRange range = localDate.range(ChronoField.DAY_OF_MONTH);
        
        for(long dayOfMonth = range.getMinimum(); dayOfMonth<= range.getMaximum(); dayOfMonth++) {
            LocalDate date = localDate.withDayOfMonth((int) dayOfMonth);
            int dayOfWeek = date.get(ChronoField.DAY_OF_WEEK) ;
            if(dayOfWeek == 1) { // Monday
                retList.add(date);
            }
        }
        return retList;
    }
}
AllMondaysInSameMonthQuery_ex1.java
LocalDate localDate = LocalDate.now();

System.out.println("Today is: " + localDate );
System.out.println("All mondays in the same month:\n");

AllMondaysInSameMonthQuery query = new AllMondaysInSameMonthQuery();

// Same as: mondaysInSameMonth = localDate.query(query);
List<LocalDate> mondaysInSameMonth = query.queryFrom(localDate);

for(LocalDate monday: mondaysInSameMonth)  {
    System.out.println(monday);
}
Output:
Today is: 2021-07-05
All mondays in the same month:

2021-07-05
2021-07-12
2021-07-19
2021-07-26

4. Ex: AllZoneIdsSameOffsetQuery

Créer une TemporalQuery pour chercher toutes les ZoneId(s) disponible(s) dans le système et ayant la même zone de décalage horaire (zone-offset) avec un objet TemporalAccessor.
AllZoneIdsSameOffsetQuery.java
package org.o7planning.temporalquery.ex;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

// Find all available ZoneIds with the same offset as a TemporalAccessor.
public class AllZoneIdsSameOffsetQuery implements TemporalQuery<List<ZoneId>> {

    @Override
    public List<ZoneId> queryFrom(TemporalAccessor temporal) {
        ZoneOffset offset = ZoneOffset.from(temporal);

        List<ZoneId> returnList = new ArrayList<>();
        Set<String> zoneIdNames = ZoneId.getAvailableZoneIds();

        if (temporal.isSupported(ChronoField.OFFSET_SECONDS)) {

            for (String zoneIdName : zoneIdNames) {
                ZoneId zid = ZoneId.of(zoneIdName);
                ZoneOffset os = zid.getRules().getOffset(Instant.now());

                if (offset.compareTo(os) == 0) {
                    returnList.add(zid);
                }
            }
        }
        return returnList;
    }
}
AllZoneIdsSameOffsetQuery_ex1.java
ZonedDateTime parisNow = ZonedDateTime.now(ZoneId.of("Europe/Paris"));

System.out.printf("Paris now is: %s%n", parisNow);
System.out.printf("Paris offset: %s%n", parisNow.getOffset());

AllZoneIdsSameOffsetQuery query = new AllZoneIdsSameOffsetQuery();

// Same as: sameOffsetZoneIds = parisNow.query(query);
List<ZoneId> sameOffsetZoneIds = query.queryFrom(parisNow);

System.out.printf("All available ZoneId with the same offset as %s:%n%n",parisNow.getOffset());

for(ZoneId zoneId: sameOffsetZoneIds) {
    System.out.println(zoneId.getId() +" : " + zoneId.getRules().getOffset(Instant.now()));
}
Output:
Paris now is: 2021-07-05T17:44:23.310010+02:00[Europe/Paris]
Paris offset: +02:00
All available ZoneId with the same offset as +02:00:

Africa/Cairo : +02:00
Africa/Mbabane : +02:00
Europe/Brussels : +02:00  
Africa/Harare : +02:00
.....
Africa/Khartoum : +02:00
Africa/Johannesburg : +02:00
Europe/Belgrade : +02:00
Europe/Bratislava : +02:00
Arctic/Longyearbyen : +02:00
Europe/Monaco : +02:00

5. TemporalQueries

La classe TemporalQueries fournit des méthodes statiques pour obtenir des objets TemporalQuery courants et utiles. Les informations reçues peuvent être:
  • Chronology
  • LocalDate
  • LocalTime
  • ZoneOffset
  • Precision
  • Zone
  • ZoneId