codestory

Die Anleitung zu Java TemporalQuery

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

1. TemporalQuery

Die Interface TemporalQuery ist ein Tool zum Abfragen eines Objekts TemporalAccessor, um Informationen zu extrahieren. Grundsätzlich existiert TemporalQuery, um die Abfrageinformationen des Objekts TemporalAccessor zu externalisieren, anstatt die Informationen direkt zu extrahieren.
@FunctionalInterface
public interface TemporalQuery<R> {
    R queryFrom(TemporalAccessor temporal);
}
Beispiel: Wir schreiben die Klasse HourMinuteQuery, um Stunden- und Minuteninformationen als String "HH:mm" aus Objekt TemporalAccessor zu extrahieren.
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;
    }
}
Verwenden Sie 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
Es gibt zwei Möglichkeiten, ein Objekt TemporalAccessor abzufragen, wobei der zweite Ansatz empfohlen wird.
// These two lines are equivalent, but the second approach is recommended
information = thisQuery.queryFrom(temporalAccessor);  // (1)
information = temporalAccessor.query(thisQuery);          // (2)

2. Ex: AllLeapYearsInSameDecadeQuery

Erstellen Sie eine TemporalQuery, um alle Schaltjahre im selben Jahrzehnt mit einem Objekt TemporalAccessor zu durchsuchen.
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

Erstellen Sie eine TemporalQuery, um alle Montage im selben Monat mit einem Objekt TemporalAccessor zu durchsuchen.
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

Erstellen Sie ein TemporalQuery, um alle im System verfügbaren ZoneId mit demselben Zonen-Offset wie ein Objekt TemporalAccessor zu durchsuchen.
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

Die Klasse TemporalQueries stellt statische Methoden bereit, um allgemeine und nützliche Objekte TemporalQuery abzurufen. Die erhaltenen Informationen können sein:
  • Chronology
  • LocalDate
  • LocalTime
  • ZoneOffset
  • Precision
  • Zone
  • ZoneId