diff --git a/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/DayOfMonthMatcher.java b/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/DayOfMonthMatcher.java index 2ddc1e6f3..5bc30eb23 100644 --- a/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/DayOfMonthMatcher.java +++ b/hutool-cron/src/main/java/org/dromara/hutool/cron/pattern/matcher/DayOfMonthMatcher.java @@ -55,28 +55,25 @@ public class DayOfMonthMatcher extends BoolArrayMatcher { *
  • 4月闰年匹配到29日,非闰年28日
  • * * - * @param value 指定的值 - * @param month 月份,从1开始 + * @param value 指定的值 + * @param month 月份,从1开始 * @param isLeapYear 是否为闰年 * @return 匹配到的值或之后的值 */ public int nextAfter(int value, final int month, final boolean isLeapYear) { - final int minValue = this.minValue; + final int minValue = getMinValue(month, isLeapYear); if (value > minValue) { final boolean[] bValues = this.bValues; - final int lastDay = getLastDay(month, isLeapYear); - while (value < lastDay) { + while (value < bValues.length) { if (bValues[value]) { + if(31 == value){ + // value == lastDay + return getLastDay(month, isLeapYear); + } return value; } value++; } - - // value == lastDay - if(test(31)){ - // 匹配当月最后一天 - return value; - } } // 两种情况返回最小值 @@ -85,6 +82,22 @@ public class DayOfMonthMatcher extends BoolArrayMatcher { return minValue; } + /** + * 获取匹配的最小值 + * + * @param month 月,base1 + * @param isLeapYear 是否闰年 + * @return 匹配的最小值 + */ + public int getMinValue(final int month, final boolean isLeapYear) { + final int minValue = super.getMinValue(); + if (31 == minValue) { + // 用户指定了 L 等表示最后一天 + return getLastDay(month, isLeapYear); + } + return minValue; + } + /** * 是否匹配本月最后一天,规则如下: *
    @@ -93,8 +106,8 @@ public class DayOfMonthMatcher extends BoolArrayMatcher {
     	 * 3、表达式包含最后一天(使用31表示)
     	 * 
    * - * @param value 被检查的值 - * @param lastDay 月份的最后一天 + * @param value 被检查的值 + * @param lastDay 月份的最后一天 * @return 是否为本月最后一天 */ private boolean matchLastDay(final int value, final int lastDay) { 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 a0c2153ad..74860aca2 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 @@ -199,7 +199,7 @@ public class PatternMatcher { continue; } - if (i == Part.DAY_OF_MONTH.ordinal()) { + 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); @@ -232,7 +232,7 @@ public class PatternMatcher { continue; } - if (i == Part.DAY_OF_MONTH.ordinal()) { + 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); @@ -262,8 +262,18 @@ public class PatternMatcher { */ private void setToMin(final int[] values, final int toPart) { Part part; - for (int i = 0; i <= toPart; i++) { + for (int i = toPart; i >= 0; i--) { part = Part.of(i); + 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){ + values[i] = ((DayOfMonthMatcher) partMatcher).getMinValue(month, isLeapYear); + continue; + } + } + values[i] = getMin(part); } } 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 651fa19f8..302904af6 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 @@ -15,6 +15,7 @@ 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; import java.util.Calendar; @@ -22,13 +23,11 @@ import java.util.Calendar; public class IssueI92H5HTest { @Test void nextMatchAfterTest() { - // TODO 待解决 - // 匹配所有月,返回下一月 final DateTime date = DateUtil.parse("2022-04-08 07:44:16"); final CronPattern pattern = new CronPattern("0 0 0 L 2 ?"); //noinspection ConstantConditions final Calendar calendar = pattern.nextMatchAfter(date.toCalendar()); - Console.log(DateUtil.date(calendar)); + Assertions.assertEquals("2023-02-28 00:00:00", DateUtil.date(calendar).toString()); } }