class TimeWindowFunctions {

    public static Supplier<Boolean> isInTimeWindowPredicate(TitusRuntime titusRuntime, TimeWindow timeWindow) {
        if (isEmpty(timeWindow)) {
            return () -> true;
        }

        List<Function<DayOfWeek, Boolean>> dayPredicates = new ArrayList<>();
        timeWindow.getDays().forEach(day -> dayPredicates.add(buildDayPredicate(day)));

        List<Function<Integer, Boolean>> hourPredicates = new ArrayList<>();
        timeWindow.getHourlyTimeWindows().forEach(h -> hourPredicates.add(buildHourlyTimeWindows(h)));

        Function<DayOfWeek, Boolean> combinedDayPredicate = dayPredicates.isEmpty() ? day -> true : oneOf(dayPredicates);
        Function<Integer, Boolean> combinedHourPredicate = hourPredicates.isEmpty() ? hour -> true : oneOf(hourPredicates);

        ZoneId zoneId;
        try {
            zoneId = DateTimeExt.toZoneId(timeWindow.getTimeZone());
        } catch (Exception e) {
            titusRuntime.getCodeInvariants().unexpectedError("Unrecognized time zone (data not properly validated)", e);
            return () -> false;
        }

        return () -> {
            ZonedDateTime dateTime = Instant.ofEpochMilli(titusRuntime.getClock().wallTime()).atZone(zoneId);
            return combinedDayPredicate.apply(dateTime.getDayOfWeek()) && combinedHourPredicate.apply(dateTime.getHour());
        };
    }

}