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 fa0c4b1509..0189b81026 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 @@ -16,10 +16,13 @@ package org.springframework.integration.scheduling; +import java.util.ArrayList; import java.util.BitSet; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import org.springframework.util.StringUtils; @@ -89,22 +92,35 @@ class CronSequenceGenerator { calendar.add(Calendar.SECOND, 1); calendar.set(Calendar.MILLISECOND, 0); + List resets = new ArrayList(); + int second = calendar.get(Calendar.SECOND); - second = findNext(seconds, second, 60, calendar, Calendar.SECOND); + int updateSecond = findNext(seconds, second, 60, calendar, Calendar.SECOND, Collections. emptyList()); + if (second == updateSecond) { + resets.add(Calendar.SECOND); + } int minute = calendar.get(Calendar.MINUTE); - minute = findNext(minutes, minute, 60, calendar, Calendar.MINUTE, Calendar.SECOND); + int updateMinute = findNext(minutes, minute, 60, calendar, Calendar.MINUTE, resets); + if (minute == updateMinute) { + resets.add(Calendar.MINUTE); + } int hour = calendar.get(Calendar.HOUR_OF_DAY); - hour = findNext(hours, hour, 24, calendar, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND); + int updateHour = findNext(hours, hour, 24, calendar, Calendar.HOUR_OF_DAY, resets); + if (hour == updateHour) { + resets.add(Calendar.HOUR_OF_DAY); + } int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); - dayOfMonth = findNextDay(calendar, daysOfMonth, dayOfMonth, daysOfWeek, dayOfWeek, 366); + int updateDayOfMonth = findNextDay(calendar, daysOfMonth, dayOfMonth, daysOfWeek, dayOfWeek, 366, resets); + if (dayOfMonth == updateDayOfMonth) { + resets.add(Calendar.DAY_OF_MONTH); + } 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); + month = findNext(months, month, 12, calendar, Calendar.MONTH, resets); return calendar.getTime(); @@ -112,18 +128,19 @@ class CronSequenceGenerator { /** * @param calendar + * @param resets * @return */ private int findNextDay(Calendar calendar, BitSet daysOfMonth, int dayOfMonth, BitSet daysOfWeek, int dayOfWeek, - int max) { + int max, List resets) { 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); - reset(calendar, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND); + reset(calendar, resets); } if (count > max) { throw new IllegalStateException("Overflow in day for expression=" + pattern); @@ -146,9 +163,9 @@ class CronSequenceGenerator { * * @return the value of the calendar field that is next in the sequence */ - private int findNext(BitSet bits, int value, int max, Calendar calendar, int field, int... lowerOrders) { + private int findNext(BitSet bits, int value, int max, Calendar calendar, int field, List lowerOrders) { int nextValue = bits.nextSetBit(value); - //roll over if needed + // roll over if needed if (nextValue == -1) { calendar.add(field, max - value); nextValue = bits.nextSetBit(0); @@ -166,7 +183,7 @@ class CronSequenceGenerator { * @param calendar * @param fields */ - private void reset(Calendar calendar, int... fields) { + private void reset(Calendar calendar, List fields) { for (int field : fields) { calendar.set(field, 0); } @@ -218,7 +235,7 @@ class CronSequenceGenerator { */ 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); + setDays(bits, field, max + 1); // ... and remove it from the front bits.clear(0); } @@ -281,7 +298,7 @@ class CronSequenceGenerator { int[] result = new int[2]; if (field.contains("*")) { result[0] = 0; - result[1] = max-1; + result[1] = max - 1; return result; } if (!field.contains("-")) { 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 907e6258c3..ae65e66f20 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 @@ -117,9 +117,9 @@ public class CronTriggerTests { Date date = calendar.getTime(); calendar.add(Calendar.MINUTE, 1); calendar.set(Calendar.SECOND, 0); - assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); calendar.add(Calendar.MINUTE, 1); - assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); } @Test @@ -143,7 +143,7 @@ public class CronTriggerTests { Date date = calendar.getTime(); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.HOUR_OF_DAY, 12); - assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); calendar.set(Calendar.HOUR_OF_DAY, 13); assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); } @@ -157,10 +157,10 @@ public class CronTriggerTests { 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(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(calendar.getTime(), date = trigger.getNextRunTime(null, date)); assertEquals(3, calendar.get(Calendar.DAY_OF_MONTH)); } @@ -200,7 +200,7 @@ public class CronTriggerTests { 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)); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); calendar.set(Calendar.DAY_OF_MONTH, 2); assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); } @@ -215,7 +215,7 @@ public class CronTriggerTests { 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)); + 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)); @@ -232,7 +232,7 @@ public class CronTriggerTests { calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MONTH, 10); - assertEquals(calendar.getTime(), date=trigger.getNextRunTime(null, date)); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); calendar.set(Calendar.MONTH, 11); assertEquals(calendar.getTime(), trigger.getNextRunTime(null, date)); } @@ -290,6 +290,53 @@ public class CronTriggerTests { assertEquals(Calendar.TUESDAY, calendar.get(Calendar.DAY_OF_WEEK)); } + @Test + public void testSpecificMinuteSecond() throws Exception { + CronTrigger trigger = new CronTrigger("2 5 * * * *"); + calendar.set(Calendar.MINUTE, 4); + Date date = calendar.getTime(); + calendar.add(Calendar.MINUTE, 1); + calendar.set(Calendar.SECOND, 2); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + calendar.add(Calendar.HOUR, 1); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + } + + @Test + public void testSpecificMinuteHour() throws Exception { + CronTrigger trigger = new CronTrigger("* 5 10 * * *"); + calendar.set(Calendar.MINUTE, 4); + calendar.set(Calendar.HOUR_OF_DAY, 9); + Date date = calendar.getTime(); + calendar.add(Calendar.MINUTE, 1); + calendar.add(Calendar.HOUR_OF_DAY, 1); + calendar.set(Calendar.SECOND, 0); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + // next trigger is in one second because second is wildcard + 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"); + // This is a Saturday + calendar.set(2009, 8, 26); + date = calendar.getTime(); + // 7 am is the trigger time + calendar.set(Calendar.HOUR_OF_DAY, 7); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + // Add two days because we start on Saturday + calendar.add(Calendar.DAY_OF_MONTH, 2); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + // Next day is a week day so add one + calendar.add(Calendar.DAY_OF_MONTH, 1); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + calendar.add(Calendar.DAY_OF_MONTH, 1); + assertEquals(calendar.getTime(), date = trigger.getNextRunTime(null, date)); + } + @Test public void testDayOfWeekIndifferent() throws Exception { CronTrigger trigger1 = new CronTrigger("* * * 2 * *"); @@ -360,7 +407,6 @@ public class CronTriggerTests { assertEquals(trigger1, trigger2); } - /** * @param trigger * @param calendar