Skip to content

Commit 2715091

Browse files
authored
Merge pull request #453 from IndeedSi/402-fix-every-x-years-behavior
#402 Fix every x years behavior by checking offset in range and correcting previous value calculation in EveryFieldValueGenerator
2 parents 38cabb4 + 5c7d5ac commit 2715091

3 files changed

Lines changed: 52 additions & 48 deletions

File tree

src/main/java/com/cronutils/model/time/generator/EveryFieldValueGenerator.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,14 @@ private int getNext(int reference, Every every) {
8686
@Override
8787
public int generatePreviousValue(final int reference) throws NoSuchValueException {
8888
final Every every = (Every) cronField.getExpression();
89+
if (reference < from) {
90+
throw new NoSuchValueException();
91+
}
92+
if (reference > to) {
93+
return to;
94+
}
8995
final int period = every.getPeriod().getValue();
90-
final int remainder = reference % period;
96+
final int remainder = (reference - from) % period;
9197
if (remainder == 0) {
9298
return reference - period;
9399
} else {
@@ -100,7 +106,7 @@ protected List<Integer> generateCandidatesNotIncludingIntervalExtremes(final int
100106
final List<Integer> values = new ArrayList<>();
101107
try {
102108
final int offset = offset();
103-
if (start != offset) {
109+
if (start < offset && offset < end) {
104110
values.add(offset);
105111
}
106112
int reference = generateNextValue(start);

src/test/java/com/cronutils/Issue402Test.java

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/test/java/com/cronutils/model/time/ExecutionTimeQuartzIntegrationTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import static com.cronutils.model.CronType.QUARTZ;
4545
import static java.time.ZoneOffset.UTC;
4646
import static org.junit.Assert.assertEquals;
47+
import static org.junit.Assert.assertFalse;
4748
import static org.junit.Assert.assertNotEquals;
4849
import static org.junit.Assert.assertNotNull;
4950
import static org.junit.Assert.assertTrue;
@@ -842,6 +843,49 @@ public void testLastExecutionIssue312() {
842843
}
843844
}
844845

846+
/**
847+
* Issue #402
848+
* https://github.com/jmrozanec/cron-utils/issues/402
849+
* Fix last and next execution time when using every X years
850+
*/
851+
@Test
852+
public void testLastExecutionIssue402() {
853+
// Every 2 years at March 1st midnight
854+
ExecutionTime execution = ExecutionTime.forCron(parser.parse("0 0 0 1 3 ? 2001-2020/2"));
855+
856+
ZonedDateTime currentDateTime = ZonedDateTime.of(LocalDate.of(2015, 1, 15), LocalTime.MIDNIGHT, ZoneOffset.UTC);
857+
// Check next execution time is correct
858+
Optional<ZonedDateTime> nextExecution = execution.nextExecution(currentDateTime);
859+
assertTrue(nextExecution.isPresent());
860+
assertEquals(ZonedDateTime.of(LocalDate.of(2015, 3, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC), nextExecution.get());
861+
// Check previous execution time is correct
862+
Optional<ZonedDateTime> lastExecution = execution.lastExecution(currentDateTime);
863+
assertTrue(lastExecution.isPresent());
864+
assertEquals(ZonedDateTime.of(LocalDate.of(2013, 3, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC), lastExecution.get());
865+
866+
lastExecution = execution.lastExecution(nextExecution.get());
867+
assertTrue(lastExecution.isPresent());
868+
assertEquals(ZonedDateTime.of(LocalDate.of(2013, 3, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC), lastExecution.get());
869+
870+
// Assume the current time is before the start time of every expression, check last and next execution.ß
871+
ZonedDateTime timeBeforeStart = ZonedDateTime.of(LocalDate.of(1996, 1, 15), LocalTime.MIDNIGHT, ZoneOffset.UTC);
872+
Optional<ZonedDateTime> nextBeforeStart = execution.nextExecution(timeBeforeStart);
873+
assertTrue(nextBeforeStart.isPresent());
874+
assertEquals(ZonedDateTime.of(LocalDate.of(2001, 3, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC), nextBeforeStart.get());
875+
876+
Optional<ZonedDateTime> lastBeforeStart = execution.lastExecution(nextBeforeStart.get());
877+
assertFalse(lastBeforeStart.isPresent());
878+
879+
// Assume the current time is before the start time of every expression, check last and next execution.ß
880+
ZonedDateTime timeAfterEnd = ZonedDateTime.of(LocalDate.of(2025, 1, 15), LocalTime.MIDNIGHT, ZoneOffset.UTC);
881+
Optional<ZonedDateTime> nextAfterEnd = execution.nextExecution(timeAfterEnd);
882+
assertFalse(nextAfterEnd.isPresent());
883+
884+
Optional<ZonedDateTime> lastAfterEnd = execution.lastExecution(timeAfterEnd);
885+
assertTrue(lastAfterEnd.isPresent());
886+
assertEquals(ZonedDateTime.of(LocalDate.of(2019, 3, 1), LocalTime.MIDNIGHT, ZoneOffset.UTC), lastAfterEnd.get());
887+
}
888+
845889
/**
846890
* Issue #424
847891
* https://github.com/jmrozanec/cron-utils/issues/424

0 commit comments

Comments
 (0)