public long getNextValidTimeAfter()

in x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/Cron.java [307:701]


    public long getNextValidTimeAfter(final long time) {

        LocalDateTime afterTimeLdt = LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(time), timeZone).plusSeconds(1);
        LocalDateTimeLegacyWrapper cl = new LocalDateTimeLegacyWrapper(afterTimeLdt.with(ChronoField.MILLI_OF_SECOND, 0));

        boolean gotOne = false;
        // loop until we've computed the next time, or we've past the endTime
        while (gotOne == false) {

            if (cl.getYear() > 2999) { // prevent endless loop...
                return -1;
            }

            SortedSet<Integer> st = null;
            int t = 0;

            int sec = cl.getSecond();
            int min = cl.getMinute();

            // get second.................................................
            st = seconds.tailSet(sec);
            if (st != null && st.size() != 0) {
                sec = st.first();
            } else {
                sec = seconds.first();
                min++;
                cl.setMinute(min);
            }
            cl.setSecond(sec);

            min = cl.getMinute();
            int hr = cl.getHour();
            t = -1;

            // get minute.................................................
            st = minutes.tailSet(min);
            if (st != null && st.size() != 0) {
                t = min;
                min = st.first();
            } else {
                min = minutes.first();
                hr++;
            }
            if (min != t) {
                cl.setSecond(0);
                cl.setMinute(min);
                cl.setHour(hr);
                continue;
            }
            cl.setMinute(min);

            hr = cl.getHour();
            int day = cl.getDayOfMonth();
            t = -1;

            // get hour...................................................
            st = hours.tailSet(hr);
            if (st != null && st.size() != 0) {
                t = hr;
                hr = st.first();
            } else {
                hr = hours.first();
                day++;
            }
            if (hr != t) {
                cl.setSecond(0);
                cl.setMinute(0);
                cl.setDayOfMonth(day);
                cl.setHour(hr);
                continue;
            }
            cl.setHour(hr);

            day = cl.getDayOfMonth();
            int mon = cl.getMonth() + 1;
            // '+ 1' because calendar is 0-based for this field, and we are
            // 1-based
            t = -1;
            int tmon = mon;

            // get day...................................................
            boolean dayOfMSpec = daysOfMonth.contains(NO_SPEC) == false;
            boolean dayOfWSpec = daysOfWeek.contains(NO_SPEC) == false;
            if (dayOfMSpec && dayOfWSpec == false) { // get day by day of month rule
                st = daysOfMonth.tailSet(day);
                if (lastdayOfMonth) {
                    if (nearestWeekday == false) {
                        t = day;
                        day = getLastDayOfMonth(mon, cl.getYear());
                        day -= lastdayOffset;
                        if (t > day) {
                            mon++;
                            if (mon > 12) {
                                mon = 1;
                                tmon = 3333; // ensure test of mon != tmon further below fails
                                cl.plusYears(1);
                            }
                            day = 1;
                        }
                    } else {
                        t = day;
                        day = getLastDayOfMonth(mon, cl.getYear());
                        day -= lastdayOffset;

                        LocalDateTimeLegacyWrapper tcal = new LocalDateTimeLegacyWrapper(LocalDateTime.now(timeZone));
                        tcal.setSecond(0);
                        tcal.setMinute(0);
                        tcal.setHour(0);
                        tcal.setDayOfMonth(day);
                        tcal.setMonth(mon - 1);
                        tcal.setYear(cl.getYear());

                        int ldom = getLastDayOfMonth(mon, cl.getYear());
                        int dow = tcal.getDayOfWeek();

                        if (dow == Calendar.SATURDAY && day == 1) {
                            day += 2;
                        } else if (dow == Calendar.SATURDAY) {
                            day -= 1;
                        } else if (dow == Calendar.SUNDAY && day == ldom) {
                            day -= 2;
                        } else if (dow == Calendar.SUNDAY) {
                            day += 1;
                        }

                        tcal.setSecond(sec);
                        tcal.setMinute(min);
                        tcal.setHour(hr);
                        tcal.setDayOfMonth(day);
                        tcal.setMonth(mon - 1);
                        if (tcal.isBefore(afterTimeLdt)) {
                            day = 1;
                            mon++;
                        }
                    }
                } else if (nearestWeekday) {
                    t = day;
                    day = daysOfMonth.first();

                    LocalDateTimeLegacyWrapper tcal = new LocalDateTimeLegacyWrapper(LocalDateTime.now(timeZone));
                    tcal.setSecond(0);
                    tcal.setMinute(0);
                    tcal.setHour(0);
                    tcal.setDayOfMonth(day);
                    tcal.setMonth(mon - 1);
                    tcal.setYear(cl.getYear());

                    int ldom = getLastDayOfMonth(mon, cl.getYear());
                    int dow = tcal.getDayOfWeek();

                    if (dow == Calendar.SATURDAY && day == 1) {
                        day += 2;
                    } else if (dow == Calendar.SATURDAY) {
                        day -= 1;
                    } else if (dow == Calendar.SUNDAY && day == ldom) {
                        day -= 2;
                    } else if (dow == Calendar.SUNDAY) {
                        day += 1;
                    }

                    tcal.setSecond(sec);
                    tcal.setMinute(min);
                    tcal.setHour(hr);
                    tcal.setDayOfMonth(day);
                    tcal.setMonth(mon - 1);
                    if (tcal.isAfter(afterTimeLdt)) {
                        day = daysOfMonth.first();
                        mon++;
                    }
                } else if (st != null && st.size() != 0) {
                    t = day;
                    day = st.first();
                    // make sure we don't over-run a short month, such as february
                    int lastDay = getLastDayOfMonth(mon, cl.getYear());
                    if (day > lastDay) {
                        day = daysOfMonth.first();
                        mon++;
                    }
                } else {
                    day = daysOfMonth.first();
                    mon++;
                }

                if (day != t || mon != tmon) {
                    cl.setSecond(0);
                    cl.setMinute(0);
                    cl.setHour(0);
                    cl.setDayOfMonth(day);
                    cl.setMonth(mon - 1);
                    // '- 1' because calendar is 0-based for this field, and we
                    // are 1-based
                    continue;
                }
            } else if (dayOfWSpec && dayOfMSpec == false) { // get day by day of week rule
                if (lastdayOfWeek) { // are we looking for the last XXX day of
                    // the month?
                    int dow = daysOfWeek.first(); // desired
                    // d-o-w
                    int cDow = cl.getDayOfWeek(); // current d-o-w
                    int daysToAdd = 0;
                    if (cDow < dow) {
                        daysToAdd = dow - cDow;
                    }
                    if (cDow > dow) {
                        daysToAdd = dow + (7 - cDow);
                    }

                    int lDay = getLastDayOfMonth(mon, cl.getYear());

                    if (day + daysToAdd > lDay) { // did we already miss the
                        // last one?
                        cl.setSecond(0);
                        cl.setMinute(0);
                        cl.setHour(0);
                        cl.setDayOfMonth(1);
                        cl.setMonth(mon);
                        // no '- 1' here because we are promoting the month
                        continue;
                    }

                    // find date of last occurrence of this day in this month...
                    while ((day + daysToAdd + 7) <= lDay) {
                        daysToAdd += 7;
                    }

                    day += daysToAdd;

                    if (daysToAdd > 0) {
                        cl.setSecond(0);
                        cl.setMinute(0);
                        cl.setHour(0);
                        cl.setDayOfMonth(day);
                        cl.setMonth(mon - 1);
                        // '- 1' here because we are not promoting the month
                        continue;
                    }

                } else if (nthdayOfWeek != 0) {
                    // are we looking for the Nth XXX day in the month?
                    int dow = daysOfWeek.first(); // desired
                    // d-o-w
                    int cDow = cl.getDayOfWeek(); // current d-o-w
                    int daysToAdd = 0;
                    if (cDow < dow) {
                        daysToAdd = dow - cDow;
                    } else if (cDow > dow) {
                        daysToAdd = dow + (7 - cDow);
                    }

                    boolean dayShifted = false;
                    if (daysToAdd > 0) {
                        dayShifted = true;
                    }

                    day += daysToAdd;
                    int weekOfMonth = day / 7;
                    if (day % 7 > 0) {
                        weekOfMonth++;
                    }

                    daysToAdd = (nthdayOfWeek - weekOfMonth) * 7;
                    day += daysToAdd;
                    if (daysToAdd < 0 || day > getLastDayOfMonth(mon, cl.getYear())) {
                        cl.setSecond(0);
                        cl.setMinute(0);
                        cl.setHour(0);
                        cl.setDayOfMonth(1);
                        cl.setMonth(mon);
                        // no '- 1' here because we are promoting the month
                        continue;
                    } else if (daysToAdd > 0 || dayShifted) {
                        cl.setSecond(0);
                        cl.setMinute(0);
                        cl.setHour(0);
                        cl.setDayOfMonth(day);
                        cl.setMonth(mon - 1);
                        // '- 1' here because we are NOT promoting the month
                        continue;
                    }
                } else {
                    int cDow = cl.getDayOfWeek(); // current d-o-w
                    int dow = daysOfWeek.first(); // desired
                    // d-o-w
                    st = daysOfWeek.tailSet(cDow);
                    if (st != null && st.size() > 0) {
                        dow = st.first();
                    }

                    int daysToAdd = 0;
                    if (cDow < dow) {
                        daysToAdd = dow - cDow;
                    }
                    if (cDow > dow) {
                        daysToAdd = dow + (7 - cDow);
                    }

                    int lDay = getLastDayOfMonth(mon, cl.getYear());

                    if (day + daysToAdd > lDay) { // will we pass the end of
                        // the month?
                        cl.setSecond(0);
                        cl.setMinute(0);
                        cl.setHour(0);
                        cl.setDayOfMonth(1);
                        cl.setMonth(mon);
                        // no '- 1' here because we are promoting the month
                        continue;
                    } else if (daysToAdd > 0) { // are we swithing days?
                        cl.setSecond(0);
                        cl.setMinute(0);
                        cl.setHour(0);
                        cl.setDayOfMonth(day + daysToAdd);
                        cl.setMonth(mon - 1);
                        // '- 1' because calendar is 0-based for this field,
                        // and we are 1-based
                        continue;
                    }
                }
            } else { // dayOfWSpec && dayOfMSpec == false
                return -1;
                // throw new UnsupportedOperationException(
                // "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.");
            }
            cl.setDayOfMonth(day);

            mon = cl.getMonth() + 1;
            // '+ 1' because calendar is 0-based for this field, and we are
            // 1-based
            int year = cl.getYear();
            t = -1;

            // test for expressions that never generate a valid fire date,
            // but keep looping...
            if (year > MAX_YEAR) {
                return -1;
                // throw new ElasticsearchIllegalArgumentException("given time is not supported by cron [" + formatter.print(time) + "]");
            }

            // get month...................................................
            st = months.tailSet(mon);
            if (st != null && st.size() != 0) {
                t = mon;
                mon = st.first();
            } else {
                mon = months.first();
                year++;
            }
            if (mon != t) {
                cl.setSecond(0);
                cl.setMinute(0);
                cl.setHour(0);
                cl.setDayOfMonth(1);
                cl.setMonth(mon - 1);
                // '- 1' because calendar is 0-based for this field, and we are
                // 1-based
                cl.setYear(year);
                continue;
            }
            cl.setMonth(mon - 1);
            // '- 1' because calendar is 0-based for this field, and we are
            // 1-based

            year = cl.getYear();
            t = -1;

            // get year...................................................
            st = years.tailSet(year);
            if (st != null && st.size() != 0) {
                t = year;
                year = st.first();
            } else {
                return -1;
                // throw new ElasticsearchIllegalArgumentException("given time is not supported by cron [" + formatter.print(time) + "]");
            }

            if (year != t) {
                cl.setSecond(0);
                cl.setMinute(0);
                cl.setHour(0);
                cl.setDayOfMonth(1);
                cl.setMonth(0);
                // '- 1' because calendar is 0-based for this field, and we are
                // 1-based
                cl.setYear(year);
                continue;
            }
            cl.setYear(year);

            gotOne = true;
        } // while( done == false )

        LocalDateTime nextRuntime = cl.getLocalDateTime();

        return nextRuntime.atZone(timeZone).toInstant().toEpochMilli();
    }