diff --git a/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/PatternMatcher.java b/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/PatternMatcher.java
index 74860aca2..d97a29aae 100644
--- a/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/PatternMatcher.java
+++ b/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/PatternMatcher.java
@@ -178,10 +178,10 @@ public class PatternMatcher {
*
如果此部分下个值小于给定值,回退到上一个值获取下一个新值,之后的值置为最小值
*
*
- *
- * 秒 分 时 日 月 周 年
- * 下 <-----------------> 上
- *
+ * {@code
+ * 秒 分 时 日 月 周 年
+ * 下 <--------------------> 上
+ * }
*
* @param values 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
* @return {@link Calendar},毫秒数为0
@@ -199,13 +199,7 @@ public class PatternMatcher {
continue;
}
- if (i == Part.DAY_OF_MONTH.ordinal() && matchers[i] instanceof DayOfMonthMatcher) {
- final boolean isLeapYear = DateUtil.isLeapYear(newValues[Part.YEAR.ordinal()]);
- final int month = newValues[Part.MONTH.ordinal()];
- nextValue = ((DayOfMonthMatcher) matchers[i]).nextAfter(values[i], month, isLeapYear);
- } else {
- nextValue = matchers[i].nextAfter(values[i]);
- }
+ nextValue = getNextMatch(newValues, i, 0);
if (nextValue > values[i]) {
// 此部分正常获取新值,结束循环,后续的部分置最小值
@@ -232,13 +226,7 @@ public class PatternMatcher {
continue;
}
- if (i == Part.DAY_OF_MONTH.ordinal() && matchers[i] instanceof DayOfMonthMatcher) {
- final boolean isLeapYear = DateUtil.isLeapYear(newValues[Part.YEAR.ordinal()]);
- final int month = newValues[Part.MONTH.ordinal()];
- nextValue = ((DayOfMonthMatcher) matchers[i]).nextAfter(values[i] + 1, month, isLeapYear);
- } else {
- nextValue = matchers[i].nextAfter(values[i] + 1);
- }
+ nextValue = getNextMatch(newValues, i, 1);
if (nextValue > values[i]) {
newValues[i] = nextValue;
@@ -254,6 +242,28 @@ public class PatternMatcher {
return newValues;
}
+ /**
+ * 获取指定部分的下一个匹配值,三种结果:
+ *
+ * - 结果值大于原值:此部分已更新,后续部分取匹配的最小值。
+ * - 结果值小于原值:此部分获取到了最小值,上一个部分需要继续取下一个值。
+ * - 结果值等于原值:此部分匹配,获取下一个部分的next值
+ *
+ *
+ * @param newValues 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
+ * @param partOrdinal 序号
+ * @return 下一个值
+ */
+ private int getNextMatch(final int[] newValues, final int partOrdinal, final int plusValue) {
+ if (partOrdinal == Part.DAY_OF_MONTH.ordinal() && matchers[partOrdinal] instanceof DayOfMonthMatcher) {
+ final boolean isLeapYear = DateUtil.isLeapYear(newValues[Part.YEAR.ordinal()]);
+ final int month = newValues[Part.MONTH.ordinal()];
+ return ((DayOfMonthMatcher) matchers[partOrdinal]).nextAfter(newValues[partOrdinal] + plusValue, month, isLeapYear);
+ }
+
+ return matchers[partOrdinal].nextAfter(newValues[partOrdinal] + plusValue);
+ }
+
/**
* 设置从{@link Part#SECOND}到指定部分,全部设置为最小值
*
@@ -264,11 +274,11 @@ public class PatternMatcher {
Part part;
for (int i = toPart; i >= 0; i--) {
part = Part.of(i);
- if(part == Part.DAY_OF_MONTH){
+ if (part == Part.DAY_OF_MONTH) {
final boolean isLeapYear = DateUtil.isLeapYear(values[Part.YEAR.ordinal()]);
final int month = values[Part.MONTH.ordinal()];
final PartMatcher partMatcher = get(part);
- if(partMatcher instanceof DayOfMonthMatcher){
+ if (partMatcher instanceof DayOfMonthMatcher) {
values[i] = ((DayOfMonthMatcher) partMatcher).getMinValue(month, isLeapYear);
continue;
}
diff --git a/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/CronPatternNextMatchTest.java b/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/CronPatternNextMatchTest.java
index 2721a361a..1e413ba2d 100644
--- a/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/CronPatternNextMatchTest.java
+++ b/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/CronPatternNextMatchTest.java
@@ -100,6 +100,18 @@ public class CronPatternNextMatchTest {
Assertions.assertEquals("2022-01-12 00:12:23", DateUtil.date(calendar).toString());
}
+ @Test
+ public void nextMatchAfterTest2(){
+ final CronPattern pattern = new CronPattern("23 12 * 12 * * *");
+
+ // 秒超出规定值的最大值,分不变,小时+1,秒和分使用最小值
+ //noinspection ConstantConditions
+ final Calendar calendar = pattern.nextMatchAfter(
+ DateUtil.parse("2022-04-12 09:12:24").toCalendar());
+ Assertions.assertTrue(pattern.match(calendar, true));
+ Assertions.assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString());
+ }
+
@Test
public void nextMatchAfterByWeekTest(){
final CronPattern pattern = new CronPattern("1 1 1 * * Sat *");
diff --git a/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/IssueI92H5HTest.java b/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/IssueI92H5HTest.java
index 302904af6..148061d41 100644
--- a/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/IssueI92H5HTest.java
+++ b/hutool-cron/src/test/java/org/dromara/hutool/cron/pattern/IssueI92H5HTest.java
@@ -14,7 +14,6 @@ package org.dromara.hutool.cron.pattern;
import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil;
-import org.dromara.hutool.core.lang.Console;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;