Add support for Quartz features in CronExpression
This commit introduces support for Quartz-specific features in CronExpression. This includes support for "L", "W", and "#". Closes gh-20106 Closes gh-22436
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.springframework.scheduling.support.BitSetAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class BitsCronFieldTests {
|
||||
|
||||
@Test
|
||||
void parse() {
|
||||
assertThat(BitsCronField.parseSeconds("42").bits()).hasUnsetRange(0, 41).hasSet(42).hasUnsetRange(43, 59);
|
||||
assertThat(BitsCronField.parseMinutes("1,2,5,9").bits()).hasUnset(0).hasSet(1, 2).hasUnset(3,4).hasSet(5).hasUnsetRange(6,8).hasSet(9).hasUnsetRange(10,59);
|
||||
assertThat(BitsCronField.parseSeconds("0-4,8-12").bits()).hasSetRange(0, 4).hasUnsetRange(5,7).hasSetRange(8, 12).hasUnsetRange(13,59);
|
||||
assertThat(BitsCronField.parseHours("0-23/2").bits()).hasSet(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22).hasUnset(1,3,5,7,9,11,13,15,17,19,21,23);
|
||||
assertThat(BitsCronField.parseDaysOfWeek("0").bits()).hasUnsetRange(0, 6).hasSet(7, 7);
|
||||
assertThat(BitsCronField.parseSeconds("57/2").bits()).hasUnsetRange(0, 56).hasSet(57).hasUnset(58).hasSet(59);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidRange() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseSeconds(""));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseSeconds("0-12/0"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseSeconds("60"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseMinutes("60"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseDaysOfMonth("0"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseDaysOfMonth("32"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseMonth("0"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseMonth("13"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseDaysOfWeek("8"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> BitsCronField.parseSeconds("20-10"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseWildcards() {
|
||||
assertThat(BitsCronField.parseSeconds("*").bits()).hasSetRange(0, 60);
|
||||
assertThat(BitsCronField.parseMinutes("*").bits()).hasSetRange(0, 60);
|
||||
assertThat(BitsCronField.parseHours("*").bits()).hasSetRange(0, 23);
|
||||
assertThat(BitsCronField.parseDaysOfMonth("*").bits()).hasUnset(0).hasSetRange(1, 31);
|
||||
assertThat(BitsCronField.parseDaysOfMonth("?").bits()).hasUnset(0).hasSetRange(1, 31);
|
||||
assertThat(BitsCronField.parseMonth("*").bits()).hasUnset(0).hasSetRange(1, 12);
|
||||
assertThat(BitsCronField.parseDaysOfWeek("*").bits()).hasUnset(0).hasSetRange(1, 7);
|
||||
assertThat(BitsCronField.parseDaysOfWeek("?").bits()).hasUnset(0).hasSetRange(1, 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
void names() {
|
||||
assertThat(((BitsCronField)CronField.parseMonth("JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC")).bits())
|
||||
.hasUnset(0).hasSetRange(1, 12);
|
||||
assertThat(((BitsCronField)CronField.parseDaysOfWeek("SUN,MON,TUE,WED,THU,FRI,SAT")).bits())
|
||||
.hasUnset(0).hasSetRange(1, 7);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,11 +22,16 @@ 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 java.util.Locale;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
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.TUESDAY;
|
||||
import static java.time.DayOfWeek.WEDNESDAY;
|
||||
@@ -38,6 +43,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class CronExpressionTests {
|
||||
|
||||
private static final Condition<Temporal> weekday = new Condition<Temporal>("weekday") {
|
||||
|
||||
@Override
|
||||
public boolean matches(Temporal value) {
|
||||
int dayOfWeek = value.get(ChronoField.DAY_OF_WEEK);
|
||||
return dayOfWeek != 6 && dayOfWeek != 7;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Test
|
||||
void matchAll() {
|
||||
CronExpression expression = CronExpression.parse("* * * * * *");
|
||||
@@ -583,4 +598,504 @@ class CronExpressionTests {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void quartzLastDayOfMonth() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 L * *");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 31, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 2, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 3, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 4, 30, 0, 0);
|
||||
assertThat(expression.next(last)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartzLastDayOfMonthOffset() {
|
||||
// L-3 = third-to-last day of the month
|
||||
CronExpression expression = CronExpression.parse("0 0 0 L-3 * *");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 28, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 2, 26, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 3, 28, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 4, 27, 0, 0);
|
||||
assertThat(expression.next(last)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartzLastWeekdayOfMonth() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 LW * *");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 31, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 2, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 3, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 4, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 5, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 6, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 7, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 8, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 9, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 10, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 11, 28, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 12, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quartzLastDayOfWeekFirstDayMonday() {
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
try {
|
||||
Locale.setDefault(Locale.UK);
|
||||
|
||||
CronExpression expression = CronExpression.parse("0 0 0 * * L");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 6, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(SUNDAY);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusWeeks(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(SUNDAY);
|
||||
}
|
||||
finally {
|
||||
Locale.setDefault(defaultLocale);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quartzLastDayOfWeekFirstDaySunday() {
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
try {
|
||||
Locale.setDefault(Locale.US);
|
||||
|
||||
CronExpression expression = CronExpression.parse("0 0 0 * * L");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 5, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(SATURDAY);
|
||||
|
||||
last = actual;
|
||||
expected = expected.plusWeeks(1);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(SATURDAY);
|
||||
}
|
||||
finally {
|
||||
Locale.setDefault(defaultLocale);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quartzLastDayOfWeekOffset() {
|
||||
// last Friday (5) of the month
|
||||
CronExpression expression = CronExpression.parse("0 0 0 * * 5L");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(LocalDate.of(2008, 1, 4), LocalTime.now());
|
||||
LocalDateTime expected = LocalDateTime.of(2008, 1, 25, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 2, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 3, 28, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 4, 25, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 5, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 6, 27, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 7, 25, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 8, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 9, 26, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 10, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 11, 28, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2008, 12, 26, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartzWeekdayNearestTo15() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 15W * ?");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 15, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 2, 14, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 3, 16, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 4, 15, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartzWeekdayNearestTo1() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 1W * ?");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2019, 12, 31, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 2, 3, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 3, 2, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 4, 1, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartzWeekdayNearestTo31() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 31W * ?");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 31, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 3, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 7, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 8, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 10, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 12, 31, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual).is(weekday);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartz2ndFridayOfTheMonth() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 ? * 5#2");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 10, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 2, 14, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 3, 13, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 4, 10, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartz2ndFridayOfTheMonthDayName() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 ? * FRI#2");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 10, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 2, 14, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 3, 13, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 4, 10, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(FRIDAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void quartzFifthWednesdayOfTheMonth() {
|
||||
CronExpression expression = CronExpression.parse("0 0 0 ? * 3#5");
|
||||
|
||||
LocalDateTime last = LocalDateTime.of(2020, 1, 1, 0, 0);
|
||||
LocalDateTime expected = LocalDateTime.of(2020, 1, 29, 0, 0);
|
||||
LocalDateTime actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(WEDNESDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 4, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(WEDNESDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 7, 29, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(WEDNESDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 9, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(WEDNESDAY);
|
||||
|
||||
last = actual;
|
||||
expected = LocalDateTime.of(2020, 12, 30, 0, 0);
|
||||
actual = expression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(WEDNESDAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.springframework.scheduling.support.BitSetAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class CronFieldTests {
|
||||
|
||||
@Test
|
||||
void parse() {
|
||||
assertThat(CronField.parseSeconds("42").bits()).hasUnsetRange(0, 41).hasSet(42).hasUnsetRange(43, 59);
|
||||
assertThat(CronField.parseMinutes("1,2,5,9").bits()).hasUnset(0).hasSet(1, 2).hasUnset(3,4).hasSet(5).hasUnsetRange(6,8).hasSet(9).hasUnsetRange(10,59);
|
||||
assertThat(CronField.parseSeconds("0-4,8-12").bits()).hasSetRange(0, 4).hasUnsetRange(5,7).hasSetRange(8, 12).hasUnsetRange(13,59);
|
||||
assertThat(CronField.parseHours("0-23/2").bits()).hasSet(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22).hasUnset(1,3,5,7,9,11,13,15,17,19,21,23);
|
||||
assertThat(CronField.parseDaysOfWeek("0").bits()).hasUnsetRange(0, 6).hasSet(7, 7);
|
||||
assertThat(CronField.parseSeconds("57/2").bits()).hasUnsetRange(0, 56).hasSet(57).hasUnset(58).hasSet(59);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidRange() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseSeconds(""));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseSeconds("0-12/0"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseSeconds("60"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseMinutes("60"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseDaysOfMonth("0"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseDaysOfMonth("32"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseMonth("0"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseMonth("13"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseDaysOfWeek("8"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CronField.parseSeconds("20-10"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseWildcards() {
|
||||
assertThat(CronField.parseSeconds("*").bits()).hasSetRange(0, 60);
|
||||
assertThat(CronField.parseMinutes("*").bits()).hasSetRange(0, 60);
|
||||
assertThat(CronField.parseHours("*").bits()).hasSetRange(0, 23);
|
||||
assertThat(CronField.parseDaysOfMonth("*").bits()).hasUnset(0).hasSetRange(1, 31);
|
||||
assertThat(CronField.parseDaysOfMonth("?").bits()).hasUnset(0).hasSetRange(1, 31);
|
||||
assertThat(CronField.parseMonth("*").bits()).hasUnset(0).hasSetRange(1, 12);
|
||||
assertThat(CronField.parseDaysOfWeek("*").bits()).hasUnset(0).hasSetRange(1, 7);
|
||||
assertThat(CronField.parseDaysOfWeek("?").bits()).hasUnset(0).hasSetRange(1, 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
void names() {
|
||||
assertThat(CronField.parseMonth("JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC").bits())
|
||||
.hasUnset(0).hasSetRange(1, 12);
|
||||
assertThat(CronField.parseDaysOfWeek("SUN,MON,TUE,WED,THU,FRI,SAT").bits())
|
||||
.hasUnset(0).hasSetRange(1, 7);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.time.DayOfWeek.SATURDAY;
|
||||
import static java.time.DayOfWeek.SUNDAY;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class QuartzCronFieldTests {
|
||||
|
||||
@Test
|
||||
void lastDayOfMonth() {
|
||||
QuartzCronField field = QuartzCronField.parseDaysOfMonth("L");
|
||||
|
||||
LocalDate last = LocalDate.of(2020, 6, 16);
|
||||
LocalDate expected = LocalDate.of(2020, 6, 30);
|
||||
assertThat(field.nextOrSame(last)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void lastDayOfMonthOffset() {
|
||||
QuartzCronField field = QuartzCronField.parseDaysOfMonth("L-3");
|
||||
|
||||
LocalDate last = LocalDate.of(2020, 6, 16);
|
||||
LocalDate expected = LocalDate.of(2020, 6, 27);
|
||||
assertThat(field.nextOrSame(last)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void lastWeekdayOfMonth() {
|
||||
QuartzCronField field = QuartzCronField.parseDaysOfMonth("LW");
|
||||
|
||||
LocalDate last = LocalDate.of(2020, 6, 16);
|
||||
LocalDate expected = LocalDate.of(2020, 6, 30);
|
||||
LocalDate actual = field.nextOrSame(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(DayOfWeek.TUESDAY);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastDayOfWeekFirstDayMonday() {
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
try {
|
||||
Locale.setDefault(Locale.UK);
|
||||
QuartzCronField field = QuartzCronField.parseDaysOfWeek("L");
|
||||
|
||||
LocalDate last = LocalDate.of(2020, 6, 16);
|
||||
LocalDate expected = LocalDate.of(2020, 6, 21);
|
||||
assertThat(field.nextOrSame(last)).isEqualTo(expected);
|
||||
|
||||
LocalDate actual = field.nextOrSame(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(SUNDAY);
|
||||
}
|
||||
finally {
|
||||
Locale.setDefault(defaultLocale);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lastDayOfWeekFirstDaySunday() {
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
try {
|
||||
Locale.setDefault(Locale.US);
|
||||
QuartzCronField field = QuartzCronField.parseDaysOfWeek("L");
|
||||
|
||||
LocalDate last = LocalDate.of(2020, 6, 16);
|
||||
LocalDate expected = LocalDate.of(2020, 6, 20);
|
||||
assertThat(field.nextOrSame(last)).isEqualTo(expected);
|
||||
|
||||
LocalDate actual = field.nextOrSame(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
assertThat(actual.getDayOfWeek()).isEqualTo(SATURDAY);
|
||||
}
|
||||
finally {
|
||||
Locale.setDefault(defaultLocale);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void lastDayOfWeekOffset() {
|
||||
// last Thursday (4) of the month
|
||||
QuartzCronField field = QuartzCronField.parseDaysOfWeek("4L");
|
||||
|
||||
LocalDate last = LocalDate.of(2020, 6, 16);
|
||||
LocalDate expected = LocalDate.of(2020, 6, 25);
|
||||
assertThat(field.nextOrSame(last)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidValues() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth(""));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("1L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("LL"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("4L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("0L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("W"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("W1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("WW"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfMonth("32W"));
|
||||
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek(""));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("L1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("LL"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("-4L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("8L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("#"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("1#"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("#1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("1#L"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("L#1"));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> QuartzCronField.parseDaysOfWeek("8#1"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user