From cca70d4ad2ea5fb566f44f004542001d69aaf8c8 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 4 Jun 2026 10:19:27 +0200 Subject: [PATCH] Polishing contribution This fixes a potential regression introduced by the previous commit. Because the current value was not updated after the temporal was rolled forward, there were new cases where entire days would be skipped. Closes gh-36865 --- .../scheduling/support/BitsCronField.java | 1 + .../support/BitsCronFieldTests.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/spring-context/src/main/java/org/springframework/scheduling/support/BitsCronField.java b/spring-context/src/main/java/org/springframework/scheduling/support/BitsCronField.java index 494cfd6c540..d914ea3fbd5 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/support/BitsCronField.java +++ b/spring-context/src/main/java/org/springframework/scheduling/support/BitsCronField.java @@ -200,6 +200,7 @@ final class BitsCronField extends CronField { temporal = type().rollForward(temporal); next = nextSetBit(0); } + current = type().get(temporal); } } if (count >= CronExpression.MAX_ATTEMPTS) { diff --git a/spring-context/src/test/java/org/springframework/scheduling/support/BitsCronFieldTests.java b/spring-context/src/test/java/org/springframework/scheduling/support/BitsCronFieldTests.java index d410d44de6e..7361054fc3e 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/support/BitsCronFieldTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/support/BitsCronFieldTests.java @@ -16,6 +16,7 @@ package org.springframework.scheduling.support; +import java.time.ZonedDateTime; import java.util.Arrays; import org.assertj.core.api.Condition; @@ -29,6 +30,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException * * @author Arjen Poutsma * @author Sam Brannen + * @author Brian Clozel */ class BitsCronFieldTests { @@ -112,6 +114,24 @@ class BitsCronFieldTests { .has(clear(0)).has(setRange(1, 7)); } + @Test + void nextOrSameWithMidnightGap() { + BitsCronField field = BitsCronField.parseHours("0-23/2"); + ZonedDateTime last = ZonedDateTime.parse("2025-04-24T23:00:00+02:00[Africa/Cairo]"); + ZonedDateTime expected = ZonedDateTime.parse("2025-04-25T02:00:00+03:00[Africa/Cairo]"); + ZonedDateTime actual = field.nextOrSame(last); + assertThat(actual).isEqualTo(expected); + } + + @Test + void nextOrSameWithGapAfterRollForward() { + BitsCronField field = BitsCronField.parseHours("0,2"); + ZonedDateTime last = ZonedDateTime.parse("2026-03-08T01:00:00-05:00[America/New_York]"); + ZonedDateTime expected = ZonedDateTime.parse("2026-03-09T00:00:00-04:00[America/New_York]"); + ZonedDateTime actual = field.nextOrSame(last); + assertThat(actual).isEqualTo(expected); + } + private static Condition set(int... indices) { return new Condition<>(String.format("set bits %s", Arrays.toString(indices))) {