Skip to content

Commit 4203e90

Browse files
committed
Fix CronExpression roll-forward issue
This commit makes sure that BitsCronField rolls the date forward in cases where we cannot find a next bit to elapse to. Closes: gh-26964
1 parent 1e2e114 commit 4203e90

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

spring-context/src/main/java/org/springframework/scheduling/support/BitsCronField.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -192,6 +192,11 @@ public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
192192
while (current != next && count++ < CronExpression.MAX_ATTEMPTS) {
193193
temporal = type().elapseUntil(temporal, next);
194194
current = type().get(temporal);
195+
next = nextSetBit(current);
196+
if (next == -1) {
197+
temporal = type().rollForward(temporal);
198+
next = nextSetBit(0);
199+
}
195200
}
196201
if (count >= CronExpression.MAX_ATTEMPTS) {
197202
return null;

spring-context/src/test/java/org/springframework/scheduling/support/CronExpressionTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,29 @@ void friday13th() {
497497
assertThat(actual.getDayOfMonth()).isEqualTo(13);
498498
}
499499

500+
@Test
501+
public void everyTenDays() {
502+
CronExpression cronExpression = CronExpression.parse("0 15 12 */10 1-8 5");
503+
504+
LocalDateTime last = LocalDateTime.parse("2021-04-30T12:14:59");
505+
LocalDateTime expected = LocalDateTime.parse("2021-05-21T12:15");
506+
LocalDateTime actual = cronExpression.next(last);
507+
assertThat(actual).isNotNull();
508+
assertThat(actual).isEqualTo(expected);
509+
510+
last = actual;
511+
expected = LocalDateTime.parse("2021-06-11T12:15");
512+
actual = cronExpression.next(last);
513+
assertThat(actual).isNotNull();
514+
assertThat(actual).isEqualTo(expected);
515+
516+
last = actual;
517+
expected = LocalDateTime.parse("2022-01-21T12:15");
518+
actual = cronExpression.next(last);
519+
assertThat(actual).isNotNull();
520+
assertThat(actual).isEqualTo(expected);
521+
}
522+
500523
@Test
501524
void yearly() {
502525
CronExpression expression = CronExpression.parse("@yearly");

0 commit comments

Comments
 (0)