package org.oddjob.schedules.schedules; import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import junit.framework.TestCase; import org.apache.log4j.Logger; import org.oddjob.arooa.utils.DateHelper; import org.oddjob.arooa.utils.SpringSafeCalendar; import org.oddjob.arooa.utils.TimeParser; import org.oddjob.schedules.IntervalTo; import org.oddjob.schedules.ScheduleResult; import org.oddjob.schedules.ScheduleRoller; public class DailyOverDSTBoundryTest extends TestCase { private static final Logger logger = Logger.getLogger(DailyOverDSTBoundryTest.class); @Override protected void setUp() throws Exception { super.setUp(); logger.info("-------------------- " + getName() + " ----------------------"); } /** * How does a Calendar behave at daylight saving time? * <p> * When the clocks go back in autumn there is an extra hour. In * the UK this is 01:00 to 02:00 BST. At 02:00 BST the time becomes 01:00 * GMT. * <p> * The time format will parse 01:00 as 01:00 GMT. A daily schedule * running from before the Sunday will be due at 01:00 BST Sunday, * 24 hours after it last ran. But will then be due at 01:00 GMT Monday, * 25 hours later. * <p>The same daily schedule started after Midnight on the Sunday will * be due at 01:00 GMT Sunday and then 01:00 GMT Monday, only 24 hours later. * */ public void testCalendarAssuptionsAutumn() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); // Autumn Date saturday1AM_BST = DateHelper.parseDateTime("2005-10-29 01:00"); Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("Europe/London")); cal1.setTime(saturday1AM_BST); cal1.add(Calendar.DATE, 1); assertEquals(1 * 60 * 60 * 1000L, cal1.get(Calendar.DST_OFFSET)); Date sunday1AM_BST = new Date(DateHelper.parseDateTime("2005-10-30 00:59:59.999").getTime() + 1); logger.info("Sunday 1am BST: " + saturday1AM_BST); assertEquals(sunday1AM_BST, cal1.getTime()); cal1.add(Calendar.HOUR, 1); Date sunday1AM_GMT = DateHelper.parseDateTime("2005-10-30 01:00"); logger.info("Sunday 1am GMT: " + sunday1AM_GMT); assertEquals(sunday1AM_GMT, cal1.getTime()); TimeZone.setDefault(null); } /** * Adding a day to 1am Saturday is midnight Sunday (23 hours later) * * @throws ParseException */ public void testCalendarAssuptionsSpring() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); // Spring // First with midnight Date saturday_Midnight = DateHelper.parseDateTime("2005-03-26 00:00"); Calendar cal1 = Calendar.getInstance(); cal1.setTime(saturday_Midnight); cal1.add(Calendar.DATE, 1); Date sundayMidnight_GMT = DateHelper.parseDateTime("2005-03-27 00:00"); assertEquals(sundayMidnight_GMT, cal1.getTime()); // Then from 1 am - same outcome! Date saturday1AM_GMT = DateHelper.parseDateTime("2005-03-26 01:00"); Calendar cal2 = Calendar.getInstance(); cal2.setTime(saturday1AM_GMT); cal2.add(Calendar.DATE, 1); assertEquals(sundayMidnight_GMT, cal2.getTime()); // Check it's 23 hours. assertEquals(23 * 60 * 60 * 1000L, sundayMidnight_GMT.getTime() - saturday1AM_GMT.getTime()); cal2.add(Calendar.HOUR, 1); Date sunday_2AM_BST = DateHelper.parseDateTime("2005-03-27 02:00"); logger.info("Sunday 2am BST: " + sunday_2AM_BST); assertEquals(sunday_2AM_BST, cal2.getTime()); TimeZone.setDefault(null); } public void testDateParsing() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); Calendar cal = Calendar.getInstance(); // What happens to 1am in Spring? It is 2am BST. Date oneAM = DateHelper.parseDateTime("2005-03-27 01:05"); logger.info("2005-03-27 01:05 is " + oneAM); cal.setTime(oneAM); assertEquals(1 * 60 * 60 * 1000L, cal.get(Calendar.DST_OFFSET)); assertEquals(2, cal.get(Calendar.HOUR)); Date twoAM = DateHelper.parseDateTime("2005-03-27 02:05"); cal.setTime(twoAM); assertEquals(1 * 60 * 60 * 1000L, cal.get(Calendar.DST_OFFSET)); assertEquals(2, cal.get(Calendar.HOUR)); assertEquals(oneAM, twoAM); Date midnightGMT = DateHelper.parseDateTime("2005-03-27 00:55"); logger.info("2005-03-27 00:55 is " + midnightGMT); cal.setTime(midnightGMT); assertEquals(0L, cal.get(Calendar.DST_OFFSET)); assertEquals(0, cal.get(Calendar.HOUR)); // Time between? long interval = DateHelper.parseDateTime("2005-03-27 01:05").getTime() - DateHelper.parseDateTime("2005-03-27 00:55").getTime(); assertEquals(10 * 60 * 1000L, interval); interval = DateHelper.parseDateTime("2005-03-27 02:05").getTime() - DateHelper.parseDateTime("2005-03-27 01:55").getTime(); assertEquals(-50 * 60 * 1000L, interval); interval = DateHelper.parseDateTime("2005-03-27 02:05").getTime() - DateHelper.parseDateTime("2005-03-27 00:55").getTime(); assertEquals(10 * 60 * 1000L, interval); } // // At boundary start. public void testDayLightSavingInAutumnWithAtBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setAt("01:00"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDateTime("2005-10-28 12:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-10-29 01:00")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-30 01:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-31 01:00")); assertEquals(expected, results[2]); TimeZone.setDefault(null); } public void testDayLightSavingInSpringWithAtBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setAt("01:00"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom(DateHelper.parseDate("2005-03-26 00:00")); IntervalTo expected = new IntervalTo( DateHelper.parseDateTime("2005-03-26 01:00")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-27 01:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-28 01:00")); assertEquals(expected, results[2]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-29 01:00")); assertEquals(expected, results[3]); TimeZone.setDefault(null); } // // At boundary end. public void testDayLightSavingInAutumnWithAtBoundry2() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setAt("02:00"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDateTime("2005-10-28 12:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-10-29 02:00")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-30 02:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-31 02:00")); assertEquals(expected, results[2]); TimeZone.setDefault(null); } public void testDayLightSavingInSpringWithAtBoundry2() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setAt("02:00"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom(DateHelper.parseDate("2005-03-26 00:00")); IntervalTo expected = new IntervalTo( DateHelper.parseDateTime("2005-03-26 02:00")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-27 02:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-28 02:00")); assertEquals(expected, results[2]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-29 02:00")); assertEquals(expected, results[3]); TimeZone.setDefault(null); } // // On boundary. public void testDayLightSavingInAutumnWithFromToOnBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("01:00"); test.setTo("02:00"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDateTime("2005-10-28 12:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-10-29 01:00"), DateHelper.parseDateTime("2005-10-29 02:00")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-30 01:00"), DateHelper.parseDateTime("2005-10-30 02:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-31 01:00"), DateHelper.parseDateTime("2005-10-31 02:00")); assertEquals(expected, results[2]); TimeZone.setDefault(null); } public void testDayLightSavingInSpringWithFromToOnBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("01:00"); test.setTo("02:00"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom(DateHelper.parseDate("2005-03-26 00:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-03-26 01:00"), DateHelper.parseDateTime("2005-03-26 02:00")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-27 01:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-28 01:00"), DateHelper.parseDateTime("2005-03-28 02:00")); assertEquals(expected, results[2]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-29 01:00"), DateHelper.parseDateTime("2005-03-29 02:00")); assertEquals(expected, results[3]); TimeZone.setDefault(null); } // // Spanning boundary start public void testDayLightSavingInAutumnWithFromToSpanningBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("00:45"); test.setTo("01:15"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDateTime("2005-10-28 12:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-10-29 00:45"), DateHelper.parseDateTime("2005-10-29 01:15")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-30 00:45"), DateHelper.parseDateTime("2005-10-30 01:15")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-31 00:45"), DateHelper.parseDateTime("2005-10-31 01:15")); assertEquals(expected, results[2]); TimeZone.setDefault(null); } public void testDayLightSavingInSpringWithFromToSpanningBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("00:45"); test.setTo("01:15"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom(DateHelper.parseDate("2005-03-26 00:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-03-26 00:45"), DateHelper.parseDateTime("2005-03-26 01:15")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-27 00:45"), DateHelper.parseDateTime("2005-03-27 02:00")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-28 00:45"), DateHelper.parseDateTime("2005-03-28 01:15")); assertEquals(expected, results[2]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-29 00:45"), DateHelper.parseDateTime("2005-03-29 01:15")); assertEquals(expected, results[3]); TimeZone.setDefault(null); } // // Spanning boundary end public void testDayLightSavingInAutumnWithFromToSpanningBoundry2() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("01:45"); test.setTo("02:15"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDateTime("2005-10-28 12:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-10-29 01:45"), DateHelper.parseDateTime("2005-10-29 02:15")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-30 01:45"), DateHelper.parseDateTime("2005-10-30 02:15")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-31 01:45"), DateHelper.parseDateTime("2005-10-31 02:15")); assertEquals(expected, results[2]); TimeZone.setDefault(null); } /** * This is the test that proves the need for {@link TimeParser} with {@link SpringSafeCalendar}. * * @throws ParseException */ public void testDayLightSavingInSpringWithFromToSpanningBoundry2() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("01:45"); test.setTo("02:15"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom(DateHelper.parseDate("2005-03-26 00:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-03-26 01:45"), DateHelper.parseDateTime("2005-03-26 02:15")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-27 02:00"), DateHelper.parseDateTime("2005-03-27 02:15")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-28 01:45"), DateHelper.parseDateTime("2005-03-28 02:15")); assertEquals(expected, results[2]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-29 01:45"), DateHelper.parseDateTime("2005-03-29 02:15")); assertEquals(expected, results[3]); TimeZone.setDefault(null); } // // Over Midnight (from > to) public void testDayLightSavingInAutumnOverMidnightSpanningBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("01:30"); test.setTo("00:30"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDateTime("2005-10-28 12:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-10-28 01:30"), DateHelper.parseDateTime("2005-10-29 00:30")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-29 01:30"), DateHelper.parseDateTime("2005-10-30 00:30")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-10-30 01:30"), DateHelper.parseDateTime("2005-10-31 00:30")); assertEquals(expected, results[2]); TimeZone.setDefault(null); } public void testDayLightSavingInSpringOverMidnightSpanningBoundry() throws ParseException { TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); DailySchedule test = new DailySchedule(); test.setFrom("01:30"); test.setTo("00:30"); ScheduleRoller roller = new ScheduleRoller(test); ScheduleResult[] results = roller.resultsFrom( DateHelper.parseDate("2005-03-26 00:00")); ScheduleResult expected; expected = new IntervalTo( DateHelper.parseDateTime("2005-03-25 01:30"), DateHelper.parseDateTime("2005-03-26 00:30")); assertEquals(expected, results[0]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-26 01:30"), DateHelper.parseDateTime("2005-03-27 00:30")); assertEquals(expected, results[1]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-27 02:00"), DateHelper.parseDateTime("2005-03-28 00:30")); assertEquals(expected, results[2]); expected = new IntervalTo( DateHelper.parseDateTime("2005-03-28 01:30"), DateHelper.parseDateTime("2005-03-29 00:30")); assertEquals(expected, results[3]); TimeZone.setDefault(null); } }