diff --git a/src/main/java/com/coreoz/wisp/schedule/FixedHourSchedule.java b/src/main/java/com/coreoz/wisp/schedule/FixedHourSchedule.java index 60a7aa2..1c4ad5d 100644 --- a/src/main/java/com/coreoz/wisp/schedule/FixedHourSchedule.java +++ b/src/main/java/com/coreoz/wisp/schedule/FixedHourSchedule.java @@ -64,8 +64,9 @@ long durationUntilNextExecutionInMillis(long currentTimeInMillis, Long lastExecu } private ZonedDateTime nextExecutionDateTime(ZonedDateTime currentDateTime, boolean nextExecutionShouldBeNextDay) { - if(!nextExecutionShouldBeNextDay && currentDateTime.toLocalTime().compareTo(executionTime) <= 0) { - return executionTime.atDate(currentDateTime.toLocalDate()).atZone(zoneId); + ZonedDateTime executionDateTime = executionTime.atDate(currentDateTime.toLocalDate()).atZone(zoneId); + if(!nextExecutionShouldBeNextDay && !executionDateTime.isBefore(currentDateTime)) { + return executionDateTime; } return executionTime.atDate(currentDateTime.toLocalDate()).plusDays(1).atZone(zoneId); } diff --git a/src/test/java/com/coreoz/wisp/schedule/FixedHourScheduleTest.java b/src/test/java/com/coreoz/wisp/schedule/FixedHourScheduleTest.java index 5c2274d..96f60bf 100644 --- a/src/test/java/com/coreoz/wisp/schedule/FixedHourScheduleTest.java +++ b/src/test/java/com/coreoz/wisp/schedule/FixedHourScheduleTest.java @@ -9,6 +9,11 @@ import org.junit.Test; +import com.coreoz.wisp.Job; +import com.coreoz.wisp.JobStatus; +import com.coreoz.wisp.Scheduler; +import com.coreoz.wisp.SchedulerConfig; + public class FixedHourScheduleTest { @Test @@ -130,4 +135,40 @@ public void should_not_return_current_time_if_last_execution_equals_current_time ).isEqualTo(24 * 60 * 60 * 1000); } + @Test + public void should_skip_past_execution_during_repeated_hour() { + ZoneId zone = ZoneId.of("Europe/Paris"); + long currentTime = ZonedDateTime.parse("2016-10-30T02:15+01:00[Europe/Paris]").toInstant().toEpochMilli(); + long nextDay = ZonedDateTime.parse("2016-10-31T02:30+01:00[Europe/Paris]").toInstant().toEpochMilli(); + + assertThat(new FixedHourSchedule("02:30", zone).nextExecutionInMillis(currentTime, 0, null)) + .isEqualTo(nextDay); + } + + @Test + public void should_wait_for_adjusted_execution_during_spring_gap() { + ZoneId zone = ZoneId.of("Europe/Paris"); + long currentTime = ZonedDateTime.parse("2016-03-27T03:15+02:00[Europe/Paris]").toInstant().toEpochMilli(); + long executionTime = ZonedDateTime.parse("2016-03-27T03:30+02:00[Europe/Paris]").toInstant().toEpochMilli(); + long nextDay = ZonedDateTime.parse("2016-03-28T02:30+02:00[Europe/Paris]").toInstant().toEpochMilli(); + FixedHourSchedule schedule = new FixedHourSchedule("02:30", zone); + + assertThat(schedule.nextExecutionInMillis(currentTime, 0, null)).isEqualTo(executionTime); + assertThat(schedule.nextExecutionInMillis(executionTime, 0, null)).isEqualTo(executionTime); + assertThat(schedule.nextExecutionInMillis(executionTime, 1, executionTime)).isEqualTo(nextDay); + assertThat(schedule.nextExecutionInMillis(executionTime + 1, 1, executionTime)).isEqualTo(nextDay); + } + + @Test + public void should_keep_daily_job_scheduled_during_repeated_hour() { + long currentTime = ZonedDateTime.parse("2016-10-30T02:15+01:00[Europe/Paris]").toInstant().toEpochMilli(); + long nextDay = ZonedDateTime.parse("2016-10-31T02:30+01:00[Europe/Paris]").toInstant().toEpochMilli(); + try (Scheduler scheduler = new Scheduler(SchedulerConfig.builder().timeProvider(() -> currentTime).build())) { + Job job = scheduler.schedule("daily", () -> {}, new FixedHourSchedule("02:30", ZoneId.of("Europe/Paris"))); + + assertThat(job.status()).isEqualTo(JobStatus.SCHEDULED); + assertThat(job.nextExecutionTimeInMillis()).isEqualTo(nextDay); + } + } + }