diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/scheduling/CronSequenceGenerator.java b/org.springframework.integration/src/main/java/org/springframework/integration/scheduling/CronSequenceGenerator.java index 0189b81026..6c931a6240 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/scheduling/CronSequenceGenerator.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/scheduling/CronSequenceGenerator.java @@ -85,6 +85,25 @@ class CronSequenceGenerator { */ public Date next(Date date) { + /* + The plan: + + 1 Round up to the next whole second + + 2 If seconds match move on, otherwise find the next match: + 2.1 If next match is in the next minute then roll forwards + + 3 If minute matches move on, otherwise find the next match + 3.1 If next match is in the next hour then roll forwards + 3.2 Reset the seconds and go to 2 + + 4 If hour matches move on, otherwise find the next match + 4.1 If next match is in the next day then roll forwards, + 4.2 Reset the minutes and seconds and go to 2 + + ... + */ + Calendar calendar = new GregorianCalendar(); calendar.setTime(date); @@ -92,10 +111,16 @@ class CronSequenceGenerator { calendar.add(Calendar.SECOND, 1); calendar.set(Calendar.MILLISECOND, 0); + doNext(calendar); + return calendar.getTime(); + } + + private void doNext(Calendar calendar) { List resets = new ArrayList(); int second = calendar.get(Calendar.SECOND); - int updateSecond = findNext(seconds, second, 60, calendar, Calendar.SECOND, Collections. emptyList()); + List emptyList = Collections. emptyList(); + int updateSecond = findNext(seconds, second, 60, calendar, Calendar.SECOND, emptyList); if (second == updateSecond) { resets.add(Calendar.SECOND); } @@ -105,12 +130,18 @@ class CronSequenceGenerator { if (minute == updateMinute) { resets.add(Calendar.MINUTE); } + else { + doNext(calendar); + } int hour = calendar.get(Calendar.HOUR_OF_DAY); int updateHour = findNext(hours, hour, 24, calendar, Calendar.HOUR_OF_DAY, resets); if (hour == updateHour) { resets.add(Calendar.HOUR_OF_DAY); } + else { + doNext(calendar); + } int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); @@ -118,12 +149,15 @@ class CronSequenceGenerator { if (dayOfMonth == updateDayOfMonth) { resets.add(Calendar.DAY_OF_MONTH); } + else { + doNext(calendar); + } int month = calendar.get(Calendar.MONTH); - month = findNext(months, month, 12, calendar, Calendar.MONTH, resets); - - return calendar.getTime(); - + int updateMonth = findNext(this.months, month, 12, calendar, Calendar.MONTH, resets); + if (month != updateMonth) { + doNext(calendar); + } } /** diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/scheduling/CronTriggerTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/scheduling/CronTriggerTests.java index ae65e66f20..1fe479b4af 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/scheduling/CronTriggerTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/scheduling/CronTriggerTests.java @@ -302,6 +302,20 @@ public class CronTriggerTests { assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); } + @Test + public void testSpecificHourSecond() throws Exception { + CronTrigger trigger = new CronTrigger("55 * 2 * * *"); + calendar.set(Calendar.HOUR_OF_DAY, 1); + calendar.set(Calendar.SECOND, 54); + Date date = calendar.getTime(); + calendar.add(Calendar.HOUR_OF_DAY, 1); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 55); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + calendar.add(Calendar.MINUTE, 1); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + } + @Test public void testSpecificMinuteHour() throws Exception { CronTrigger trigger = new CronTrigger("* 5 10 * * *"); @@ -317,6 +331,36 @@ public class CronTriggerTests { assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); } + @Test + public void testSpecificDayOfMonthSecond() throws Exception { + CronTrigger trigger = new CronTrigger("55 * * 3 * *"); + calendar.set(Calendar.DAY_OF_MONTH, 2); + calendar.set(Calendar.SECOND, 54); + Date date = calendar.getTime(); + calendar.add(Calendar.DAY_OF_MONTH, 1); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 55); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + calendar.add(Calendar.MINUTE, 1); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + } + + @Test + public void testSpecificDate() throws Exception { + CronTrigger trigger = new CronTrigger("* * * 3 10 *"); + calendar.set(Calendar.DAY_OF_MONTH, 2); + calendar.set(Calendar.MONTH, 10); + Date date = calendar.getTime(); + calendar.add(Calendar.DAY_OF_MONTH, 1); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + calendar.add(Calendar.SECOND, 1); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + } + @Test public void testWeekDaySequence() throws Exception { CronTrigger trigger = new CronTrigger("0 0 7 ? * MON-FRI");