Browse Source

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
pull/26980/head
Arjen Poutsma 4 years ago
parent
commit
4203e90655
  1. 7
      spring-context/src/main/java/org/springframework/scheduling/support/BitsCronField.java
  2. 23
      spring-context/src/test/java/org/springframework/scheduling/support/CronExpressionTests.java

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -192,6 +192,11 @@ final class BitsCronField extends CronField { @@ -192,6 +192,11 @@ final class BitsCronField extends CronField {
while (current != next && count++ < CronExpression.MAX_ATTEMPTS) {
temporal = type().elapseUntil(temporal, next);
current = type().get(temporal);
next = nextSetBit(current);
if (next == -1) {
temporal = type().rollForward(temporal);
next = nextSetBit(0);
}
}
if (count >= CronExpression.MAX_ATTEMPTS) {
return null;

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

@ -497,6 +497,29 @@ class CronExpressionTests { @@ -497,6 +497,29 @@ class CronExpressionTests {
assertThat(actual.getDayOfMonth()).isEqualTo(13);
}
@Test
public void everyTenDays() {
CronExpression cronExpression = CronExpression.parse("0 15 12 */10 1-8 5");
LocalDateTime last = LocalDateTime.parse("2021-04-30T12:14:59");
LocalDateTime expected = LocalDateTime.parse("2021-05-21T12:15");
LocalDateTime actual = cronExpression.next(last);
assertThat(actual).isNotNull();
assertThat(actual).isEqualTo(expected);
last = actual;
expected = LocalDateTime.parse("2021-06-11T12:15");
actual = cronExpression.next(last);
assertThat(actual).isNotNull();
assertThat(actual).isEqualTo(expected);
last = actual;
expected = LocalDateTime.parse("2022-01-21T12:15");
actual = cronExpression.next(last);
assertThat(actual).isNotNull();
assertThat(actual).isEqualTo(expected);
}
@Test
void yearly() {
CronExpression expression = CronExpression.parse("@yearly");

Loading…
Cancel
Save