diff --git a/spring-context/src/main/java/org/springframework/scheduling/support/QuartzCronField.java b/spring-context/src/main/java/org/springframework/scheduling/support/QuartzCronField.java index ed57360d30..8e981ccea5 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/support/QuartzCronField.java +++ b/spring-context/src/main/java/org/springframework/scheduling/support/QuartzCronField.java @@ -251,43 +251,46 @@ final class QuartzCronField extends CronField { private static TemporalAdjuster weekdayNearestTo(int dayOfMonth) { return temporal -> { int current = Type.DAY_OF_MONTH.get(temporal); - int dayOfWeek = temporal.get(ChronoField.DAY_OF_WEEK); + DayOfWeek dayOfWeek = DayOfWeek.from(temporal); - if ((current == dayOfMonth && dayOfWeek < 6) || // dayOfMonth is a weekday - (dayOfWeek == 5 && current == dayOfMonth - 1) || // dayOfMonth is a Saturday, so Friday before - (dayOfWeek == 1 && current == dayOfMonth + 1) || // dayOfMonth is a Sunday, so Monday after - (dayOfWeek == 1 && dayOfMonth == 1 && current == 3)) { // dayOfMonth is the 1st, so Monday 3rd + if ((current == dayOfMonth && isWeekday(dayOfWeek)) || // dayOfMonth is a weekday + (dayOfWeek == DayOfWeek.FRIDAY && current == dayOfMonth - 1) || // dayOfMonth is a Saturday, so Friday before + (dayOfWeek == DayOfWeek.MONDAY && current == dayOfMonth + 1) || // dayOfMonth is a Sunday, so Monday after + (dayOfWeek == DayOfWeek.MONDAY && dayOfMonth == 1 && current == 3)) { // dayOfMonth is Saturday 1st, so Monday 3rd return temporal; } int count = 0; while (count++ < CronExpression.MAX_ATTEMPTS) { - temporal = Type.DAY_OF_MONTH.elapseUntil(cast(temporal), dayOfMonth); - temporal = atMidnight().adjustInto(temporal); - current = Type.DAY_OF_MONTH.get(temporal); if (current == dayOfMonth) { - dayOfWeek = temporal.get(ChronoField.DAY_OF_WEEK); + dayOfWeek = DayOfWeek.from(temporal); - if (dayOfWeek == 6) { // Saturday + if (dayOfWeek == DayOfWeek.SATURDAY) { if (dayOfMonth != 1) { - return temporal.minus(1, ChronoUnit.DAYS); + temporal = temporal.minus(1, ChronoUnit.DAYS); } else { - // exception for "1W" fields: execute on nearest Monday - return temporal.plus(2, ChronoUnit.DAYS); + // exception for "1W" fields: execute on next Monday + temporal = temporal.plus(2, ChronoUnit.DAYS); } } - else if (dayOfWeek == 7) { // Sunday - return temporal.plus(1, ChronoUnit.DAYS); - } - else { - return temporal; + else if (dayOfWeek == DayOfWeek.SUNDAY) { + temporal = temporal.plus(1, ChronoUnit.DAYS); } + return atMidnight().adjustInto(temporal); + } + else { + temporal = Type.DAY_OF_MONTH.elapseUntil(cast(temporal), dayOfMonth); + current = Type.DAY_OF_MONTH.get(temporal); } } return null; }; } + private static boolean isWeekday(DayOfWeek dayOfWeek) { + return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; + } + /** * Return a temporal adjuster that finds the last of the given doy-of-week * in a month. diff --git a/spring-context/src/test/java/org/springframework/scheduling/support/CronExpressionTests.java b/spring-context/src/test/java/org/springframework/scheduling/support/CronExpressionTests.java index 3a21f984aa..5abce9e2de 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/support/CronExpressionTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/support/CronExpressionTests.java @@ -16,13 +16,13 @@ package org.springframework.scheduling.support; +import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Year; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.time.temporal.ChronoField; import java.time.temporal.Temporal; import org.assertj.core.api.Condition; @@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test; import static java.time.DayOfWeek.FRIDAY; import static java.time.DayOfWeek.MONDAY; +import static java.time.DayOfWeek.SATURDAY; import static java.time.DayOfWeek.SUNDAY; import static java.time.DayOfWeek.THURSDAY; import static java.time.DayOfWeek.TUESDAY; @@ -46,8 +47,8 @@ class CronExpressionTests { @Override public boolean matches(Temporal value) { - int dayOfWeek = value.get(ChronoField.DAY_OF_WEEK); - return dayOfWeek != 6 && dayOfWeek != 7; + DayOfWeek dayOfWeek = DayOfWeek.from(value); + return dayOfWeek != SATURDAY && dayOfWeek != SUNDAY; } }; @@ -958,6 +959,24 @@ class CronExpressionTests { assertThat(actual).isNotNull(); assertThat(actual).isEqualTo(expected); assertThat(actual).is(weekday); + + last = LocalDateTime.of(2022, 1, 1, 0, 0); + assertThat(last.getDayOfWeek()).isEqualTo(SATURDAY); + expected = LocalDateTime.of(2022, 1, 3, 0, 0); + assertThat(expected.getDayOfWeek()).isEqualTo(MONDAY); + actual = expression.next(last); + assertThat(actual).isNotNull(); + assertThat(actual).isEqualTo(expected); + assertThat(actual).is(weekday); + + last = LocalDateTime.of(2021, 8, 1, 0,0); + assertThat(last.getDayOfWeek()).isEqualTo(SUNDAY); + expected = LocalDateTime.of(2021, 8, 2, 0, 0); + assertThat(expected.getDayOfWeek()).isEqualTo(MONDAY); + actual = expression.next(last); + assertThat(actual).isNotNull(); + assertThat(actual).isEqualTo(expected); + assertThat(actual).is(weekday); } @Test