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();
}