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 57ea90b623..d6b8c30ead 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 @@ -90,19 +90,21 @@ public class CronSequenceGenerator { calendar.set(Calendar.MILLISECOND, 0); int second = calendar.get(Calendar.SECOND); + second = findNext(seconds, second, 60, calendar, Calendar.SECOND); + int minute = calendar.get(Calendar.MINUTE); + minute = findNext(minutes, minute, 60, calendar, Calendar.MINUTE, Calendar.SECOND); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + hour = findNext(hours, hour, 24, calendar, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND); int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); - int month = calendar.get(Calendar.MONTH); + dayOfMonth = findNextDay(calendar, daysOfMonth, dayOfMonth, daysOfWeek, dayOfWeek, 366); + int month = calendar.get(Calendar.MONTH); month = findNext(months, month, 12, calendar, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND); - dayOfMonth = findNextDay(calendar, daysOfMonth, dayOfMonth, daysOfWeek, dayOfWeek, 366); - hour = findNext(hours, hour, 24, calendar, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND); - minute = findNext(minutes, minute, 60, calendar, Calendar.MINUTE, Calendar.SECOND); - second = findNext(seconds, second, 60, calendar, Calendar.SECOND); return calendar.getTime(); @@ -117,7 +119,7 @@ public class CronSequenceGenerator { int count = 0; // the DAY_OF_WEEK values in java.util.Calendar start with 1 (Sunday), // but in the cron pattern, they start with 0, so we subtract 1 here - while ((!daysOfMonth.get(dayOfMonth) || !daysOfWeek.get(dayOfWeek - 1)) && count++ < max) { + while ((!daysOfMonth.get(dayOfMonth) || !daysOfWeek.get(dayOfWeek-1)) && count++ < max) { calendar.add(Calendar.DAY_OF_MONTH, 1); dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); @@ -182,7 +184,7 @@ public class CronSequenceGenerator { setNumberHits(seconds, fields[0], 60); setNumberHits(minutes, fields[1], 60); setNumberHits(hours, fields[2], 24); - setDays(daysOfMonth, fields[3], 31); + setDaysOfMonth(daysOfMonth, fields[3], 31); setNumberHits(months, replaceOrdinals(fields[4], "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC"), 12); setDays(daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8); if (daysOfWeek.get(7)) { @@ -209,6 +211,18 @@ public class CronSequenceGenerator { return value; } + /** + * @param bits + * @param field + * @param max + */ + private void setDaysOfMonth(BitSet bits, String field, int max) { + // Days of month start with 1 (in Cron and Calendar) so add one + setDays(bits, field, max+1); + // ... and remove it from the front + bits.clear(0); + } + /** * @param bits * @param field @@ -267,7 +281,7 @@ public class CronSequenceGenerator { int[] result = new int[2]; if (field.contains("*")) { result[0] = 0; - result[1] = max; + result[1] = max-1; return result; } if (!field.contains("-")) { @@ -306,4 +320,9 @@ public class CronSequenceGenerator { * hours.hashCode() + 53 * minutes.hashCode() + 61 * seconds.hashCode(); } + @Override + public String toString() { + return getClass().getSimpleName() + ": " + pattern; + } + } 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 354904c637..907e6258c3 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 @@ -102,7 +102,7 @@ public class CronTriggerTests { @Test public void testIncrementMinuteByOne() throws Exception { - CronTrigger trigger = new CronTrigger("* 11 * * * *"); + CronTrigger trigger = new CronTrigger("0 11 * * * *"); calendar.set(Calendar.MINUTE, 10); Date date = calendar.getTime(); calendar.add(Calendar.MINUTE, 1); @@ -110,16 +110,60 @@ public class CronTriggerTests { assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); } + @Test + public void testIncrementMinute() throws Exception { + CronTrigger trigger = new CronTrigger("0 * * * * *"); + calendar.set(Calendar.MINUTE, 10); + Date date = calendar.getTime(); + calendar.add(Calendar.MINUTE, 1); + calendar.set(Calendar.SECOND, 0); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + calendar.add(Calendar.MINUTE, 1); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + } + @Test public void testIncrementMinuteAndRollover() throws Exception { - CronTrigger trigger = new CronTrigger("* 10 * * * *"); + CronTrigger trigger = new CronTrigger("0 10 * * * *"); calendar.set(Calendar.MINUTE, 11); + calendar.set(Calendar.SECOND, 0); Date date = calendar.getTime(); calendar.add(Calendar.MINUTE, 59); - calendar.set(Calendar.SECOND, 0); assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); } + @Test + public void testIncrementHour() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 * * * *"); + calendar.set(Calendar.MONTH, 9); + calendar.set(Calendar.DAY_OF_MONTH, 30); + calendar.set(Calendar.HOUR_OF_DAY, 11); + calendar.set(Calendar.MINUTE, 1); + calendar.set(Calendar.SECOND, 0); + Date date = calendar.getTime(); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.HOUR_OF_DAY, 12); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + calendar.set(Calendar.HOUR_OF_DAY, 13); + assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + } + + @Test + public void testIncrementDayOfMonth() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 0 * * *"); + calendar.set(Calendar.DAY_OF_MONTH, 1); + 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)); + assertEquals(2, calendar.get(Calendar.DAY_OF_MONTH)); + calendar.add(Calendar.DAY_OF_MONTH, 1); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + assertEquals(3, calendar.get(Calendar.DAY_OF_MONTH)); + } + @Test public void testIncrementDayOfMonthByOne() throws Exception { CronTrigger trigger = new CronTrigger("* * * 10 * *"); @@ -145,6 +189,81 @@ public class CronTriggerTests { assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); } + @Test + public void testDailyTriggerInShortMonth() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 0 * * *"); + calendar.set(Calendar.MONTH, 8); // September: 30 days + calendar.set(Calendar.DAY_OF_MONTH, 30); + Date date = calendar.getTime(); + calendar.set(Calendar.MONTH, 9); // October + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.DAY_OF_MONTH, 1); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + calendar.set(Calendar.DAY_OF_MONTH, 2); + assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + } + + @Test + public void testDailyTriggerInLongMonth() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 0 * * *"); + calendar.set(Calendar.MONTH, 9); // October: 31 days + calendar.set(Calendar.DAY_OF_MONTH, 30); + Date date = calendar.getTime(); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.DAY_OF_MONTH, 31); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + calendar.set(Calendar.MONTH, 10); // November + calendar.set(Calendar.DAY_OF_MONTH, 1); + assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + } + + @Test + public void testIncrementMonth() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 0 1 * *"); + calendar.set(Calendar.MONTH, 9); + calendar.set(Calendar.DAY_OF_MONTH, 30); + Date date = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MONTH, 10); + assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + calendar.set(Calendar.MONTH, 11); + assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + } + + @Test + public void testMonthlyTriggerInLongMonth() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 0 31 * *"); + calendar.set(Calendar.MONTH, 9); + calendar.set(Calendar.DAY_OF_MONTH, 30); + Date date = calendar.getTime(); + calendar.set(Calendar.DAY_OF_MONTH, 31); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + } + + @Test + public void testMonthlyTriggerInShortMonth() throws Exception { + CronTrigger trigger = new CronTrigger("0 0 0 1 * *"); + calendar.set(Calendar.MONTH, 9); + calendar.set(Calendar.DAY_OF_MONTH, 30); + Date date = calendar.getTime(); + calendar.set(Calendar.MONTH, 10); + calendar.set(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(), trigger.getNextRunTime(null, date)); + } + @Test public void testIncrementDayOfWeekByOne() throws Exception { CronTrigger trigger = new CronTrigger("* * * * * 2"); @@ -155,6 +274,7 @@ public class CronTriggerTests { calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + assertEquals(Calendar.TUESDAY, calendar.get(Calendar.DAY_OF_WEEK)); } @Test @@ -167,6 +287,7 @@ public class CronTriggerTests { calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); + assertEquals(Calendar.TUESDAY, calendar.get(Calendar.DAY_OF_WEEK)); } @Test @@ -204,6 +325,13 @@ public class CronTriggerTests { assertEquals(trigger1, trigger2); } + @Test + public void testSundayIsZero() throws Exception { + CronTrigger trigger1 = new CronTrigger("* * * * * 0"); + CronTrigger trigger2 = new CronTrigger("* * * * * SUN"); + assertEquals(trigger1, trigger2); + } + @Test public void testSundaySynonym() throws Exception { CronTrigger trigger1 = new CronTrigger("* * * * * 0"); @@ -225,6 +353,13 @@ public class CronTriggerTests { assertEquals(trigger1, trigger2); } + @Test + public void testWhitespace() throws Exception { + CronTrigger trigger1 = new CronTrigger("* * * * 1 *"); + CronTrigger trigger2 = new CronTrigger("* * * * 1 *"); + assertEquals(trigger1, trigger2); + } + /** * @param trigger