mirror of
https://github.com/frode-carlsen/cron.git
synced 2025-12-07 14:30:57 +03:00
The search for the next execution time can be limited by a date/time barrier so searches for february 30th will no longer result in an endless loop
This commit is contained in:
@@ -174,6 +174,20 @@ public class CronExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DateTime nextTimeAfter(DateTime afterTime) {
|
public DateTime nextTimeAfter(DateTime afterTime) {
|
||||||
|
// will search for the next time within the next 4 years. If there is no
|
||||||
|
// time matching, an InvalidArgumentException will be thrown (it is very
|
||||||
|
// likely that the cron expression is invalid, like the February 30th).
|
||||||
|
return nextTimeAfter(afterTime, afterTime.plusYears(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime nextTimeAfter(DateTime afterTime, long durationInMillis) {
|
||||||
|
// will search for the next time within the next durationInMillis
|
||||||
|
// millisecond. Be aware that the duration is specified in millis,
|
||||||
|
// but in fact the limit is checked on a day-to-day basis.
|
||||||
|
return nextTimeAfter(afterTime, afterTime.plus(durationInMillis));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime nextTimeAfter(DateTime afterTime, DateTime dateTimeBarrier) {
|
||||||
MutableDateTime nextTime = new MutableDateTime(afterTime);
|
MutableDateTime nextTime = new MutableDateTime(afterTime);
|
||||||
nextTime.setMillisOfSecond(0);
|
nextTime.setMillisOfSecond(0);
|
||||||
nextTime.secondOfDay().add(1);
|
nextTime.secondOfDay().add(1);
|
||||||
@@ -207,6 +221,7 @@ public class CronExpression {
|
|||||||
}
|
}
|
||||||
nextTime.addDays(1);
|
nextTime.addDays(1);
|
||||||
nextTime.setTime(0, 0, 0, 0);
|
nextTime.setTime(0, 0, 0, 0);
|
||||||
|
checkIfDateTimeBarrierIsReached(nextTime, dateTimeBarrier);
|
||||||
}
|
}
|
||||||
if (monthField.matches(nextTime.getMonthOfYear())) {
|
if (monthField.matches(nextTime.getMonthOfYear())) {
|
||||||
break;
|
break;
|
||||||
@@ -214,17 +229,25 @@ public class CronExpression {
|
|||||||
nextTime.addMonths(1);
|
nextTime.addMonths(1);
|
||||||
nextTime.setDayOfMonth(1);
|
nextTime.setDayOfMonth(1);
|
||||||
nextTime.setTime(0, 0, 0, 0);
|
nextTime.setTime(0, 0, 0, 0);
|
||||||
|
checkIfDateTimeBarrierIsReached(nextTime, dateTimeBarrier);
|
||||||
}
|
}
|
||||||
if (dayOfWeekField.matches(new LocalDate(nextTime))) {
|
if (dayOfWeekField.matches(new LocalDate(nextTime))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nextTime.addDays(1);
|
nextTime.addDays(1);
|
||||||
nextTime.setTime(0, 0, 0, 0);
|
nextTime.setTime(0, 0, 0, 0);
|
||||||
|
checkIfDateTimeBarrierIsReached(nextTime, dateTimeBarrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nextTime.toDateTime();
|
return nextTime.toDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkIfDateTimeBarrierIsReached(MutableDateTime nextTime, DateTime dateTimeBarrier) {
|
||||||
|
if (nextTime.isAfter(dateTimeBarrier)) {
|
||||||
|
throw new IllegalArgumentException("No next execution time could be determined that is before the limit of " + dateTimeBarrier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + "<" + expr + ">";
|
return getClass().getSimpleName() + "<" + expr + ">";
|
||||||
|
|||||||
@@ -442,4 +442,28 @@ public class CronExpressionTest {
|
|||||||
public void shall_not_not_support_rolling_period() throws Exception {
|
public void shall_not_not_support_rolling_period() throws Exception {
|
||||||
new CronExpression("* * 5-1 * * *");
|
new CronExpression("* * 5-1 * * *");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void non_existing_date_throws_exception() throws Exception {
|
||||||
|
// Will check for the next 4 years - no 30th of February is found so a IAE is thrown.
|
||||||
|
new CronExpression("* * * 30 2 *").nextTimeAfter(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_default_barrier() throws Exception {
|
||||||
|
// the default barrier is 4 years - so leap years are considered.
|
||||||
|
assertThat(new CronExpression("* * * 29 2 *").nextTimeAfter(new DateTime(2012, 3, 1, 00, 00))).isEqualTo(new DateTime(2016, 2, 29, 00, 00));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void test_one_year_barrier() throws Exception {
|
||||||
|
// The next leap year is 2016, so an IllegalArgumentException is expected.
|
||||||
|
new CronExpression("* * * 29 2 *").nextTimeAfter(new DateTime(2012, 3, 1, 00, 00), new DateTime(2013, 3, 1, 00, 00));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void test_two_year_barrier() throws Exception {
|
||||||
|
// The next leap year is 2016, so an IllegalArgumentException is expected.
|
||||||
|
new CronExpression("* * * 29 2 *").nextTimeAfter(new DateTime(2012, 3, 1, 00, 00), 1000 * 60 * 60 * 24 * 356 * 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user