package jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByHour; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByRuleIntegerAbstract; /** * By Hour * BYHOUR * RFC 5545, iCalendar 3.3.10, page 41 * * The BYHOUR rule part specifies a COMMA- * separated list of hours of the day. Valid values are 0 to 23. * * The BYSECOND, BYMINUTE and BYHOUR rule parts MUST NOT be specified * when the associated "DTSTART" property has a DATE value type. * These rule parts MUST be ignored in RECUR value that violate the * above requirement (e.g., generated by applications that pre-date * this revision of iCalendar). * * @author David Bal * */ public class ByHour extends ByRuleIntegerAbstract<ByHour> { public ByHour() { super(); } public ByHour(Integer... hours) { super(hours); } public ByHour(ByHour source) { super(source); } @Override Predicate<Integer> isValidValue() { return (value) -> (value >= 0) && (value <= 23); } @Override public Stream<Temporal> streamRecurrences(Stream<Temporal> inStream, ChronoUnit chronoUnit, Temporal dateTimeStart) { if (dateTimeStart.isSupported(ChronoField.HOUR_OF_DAY)) { switch (chronoUnit) { case HOURS: case MINUTES: case SECONDS: return inStream.filter(d -> { // filter out all but qualifying hours int myHourOfDay = d.get(ChronoField.HOUR_OF_DAY); for (int hourOfDay : getValue()) { if (hourOfDay > 0) { if (hourOfDay == myHourOfDay) return true; } } return false; }); case DAYS: case WEEKS: case MONTHS: case YEARS: return inStream.flatMap(d -> { // Expand to be include all hours of day List<Temporal> dates = new ArrayList<>(); for (int hourOfDay : getValue()) { Temporal newTemporal = d.with(ChronoField.HOUR_OF_DAY, hourOfDay); // if (! DateTimeUtilities.isBefore(newTemporal, dateTimeStart)) // { dates.add(newTemporal); // } } return dates.stream(); }); default: throw new IllegalArgumentException("Not implemented: " + chronoUnit); } } else { return inStream; // ignore rule when not supported (RFC 5545 requirement) } } public static ByHour parse(String content) { return ByHour.parse(new ByHour(), content); } }