Merge pull request #4026 from Wqh1241409260/fix-issue-4006

Fix issue 4006
This commit is contained in:
Golden Looly 2025-08-21 10:03:13 +08:00 committed by GitHub
commit f0eb62e4e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 47 additions and 7 deletions

View File

@ -54,4 +54,16 @@ public class DayOfMonthMatcher extends BoolArrayMatcher {
return match(31); return match(31);
} }
/**
* 检查value是这个月的最后一天
* @param value 被检查的值
* @return
*/
public boolean isLastDay(Integer value,Integer month, boolean isLeapYear) {
if(isLastDayOfMonth(value, month, isLeapYear)) {
return match(31);
}
return false;
}
} }

View File

@ -192,7 +192,7 @@ public class PatternMatcher {
// pr#1189 // pr#1189
if (i == Part.DAY_OF_MONTH.ordinal() if (i == Part.DAY_OF_MONTH.ordinal()
&& matchers[i] instanceof DayOfMonthMatcher && matchers[i] instanceof DayOfMonthMatcher
&& ((DayOfMonthMatcher) matchers[i]).isLast()) { && ((DayOfMonthMatcher) matchers[i]).isLastDay(values[i],values[i+1],isLeapYear(values[Part.YEAR.ordinal()]))) {
int newMonth = newValues[Part.MONTH.ordinal()]; int newMonth = newValues[Part.MONTH.ordinal()];
int newYear = newValues[Part.YEAR.ordinal()]; int newYear = newValues[Part.YEAR.ordinal()];
nextValue = getLastDay(newMonth, newYear); nextValue = getLastDay(newMonth, newYear);
@ -226,7 +226,7 @@ public class PatternMatcher {
continue; continue;
} else if (i == Part.DAY_OF_MONTH.ordinal() } else if (i == Part.DAY_OF_MONTH.ordinal()
&& matchers[i] instanceof DayOfMonthMatcher && matchers[i] instanceof DayOfMonthMatcher
&& ((DayOfMonthMatcher) matchers[i]).isLast()) { && ((DayOfMonthMatcher) matchers[i]).isLastDay(values[i],values[i+1],isLeapYear(values[Part.YEAR.ordinal()]))) {
int newMonth = newValues[Part.MONTH.ordinal()]; int newMonth = newValues[Part.MONTH.ordinal()];
int newYear = newValues[Part.YEAR.ordinal()]; int newYear = newValues[Part.YEAR.ordinal()];
nextValue = getLastDay(newMonth, newYear); nextValue = getLastDay(newMonth, newYear);
@ -247,6 +247,14 @@ public class PatternMatcher {
return newValues; return newValues;
} }
/**
* 判断年份是否是闰年
* @param year
* @return 返回boolean表示是否是闰年
*/
private static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
/** /**
* 设置从{@link Part#SECOND}到指定部分全部设置为最小值 * 设置从{@link Part#SECOND}到指定部分全部设置为最小值
* *

View File

View File

@ -54,7 +54,7 @@ public class CronPatternNextMatchTest {
// 时间正常递增 // 时间正常递增
//noinspection ConstantConditions //noinspection ConstantConditions
Calendar calendar = pattern.nextMatchAfter( Calendar calendar = pattern.nextMatchAfter(
DateUtil.parse("2022-04-12 09:12:12").toCalendar()); DateUtil.parse("2022-04-12 09:12:12").toCalendar());
assertTrue(pattern.match(calendar, true)); assertTrue(pattern.match(calendar, true));
assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString()); assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString());
@ -62,28 +62,28 @@ public class CronPatternNextMatchTest {
// 秒超出规定值的最大值+1秒取最小值 // 秒超出规定值的最大值+1秒取最小值
//noinspection ConstantConditions //noinspection ConstantConditions
calendar = pattern.nextMatchAfter( calendar = pattern.nextMatchAfter(
DateUtil.parse("2022-04-12 09:09:24").toCalendar()); DateUtil.parse("2022-04-12 09:09:24").toCalendar());
assertTrue(pattern.match(calendar, true)); assertTrue(pattern.match(calendar, true));
assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString()); assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString());
// 秒超出规定值的最大值分不变小时+1秒和分使用最小值 // 秒超出规定值的最大值分不变小时+1秒和分使用最小值
//noinspection ConstantConditions //noinspection ConstantConditions
calendar = pattern.nextMatchAfter( calendar = pattern.nextMatchAfter(
DateUtil.parse("2022-04-12 09:12:24").toCalendar()); DateUtil.parse("2022-04-12 09:12:24").toCalendar());
assertTrue(pattern.match(calendar, true)); assertTrue(pattern.match(calendar, true));
assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString()); assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString());
// 天超出规定值的最大值+1秒取最小值 // 天超出规定值的最大值+1秒取最小值
//noinspection ConstantConditions //noinspection ConstantConditions
calendar = pattern.nextMatchAfter( calendar = pattern.nextMatchAfter(
DateUtil.parse("2022-04-13 09:12:24").toCalendar()); DateUtil.parse("2022-04-13 09:12:24").toCalendar());
assertTrue(pattern.match(calendar, true)); assertTrue(pattern.match(calendar, true));
assertEquals("2022-05-12 00:12:23", DateUtil.date(calendar).toString()); assertEquals("2022-05-12 00:12:23", DateUtil.date(calendar).toString());
// 跨年 // 跨年
//noinspection ConstantConditions //noinspection ConstantConditions
calendar = pattern.nextMatchAfter( calendar = pattern.nextMatchAfter(
DateUtil.parse("2021-12-22 00:00:00").toCalendar()); DateUtil.parse("2021-12-22 00:00:00").toCalendar());
assertTrue(pattern.match(calendar, true)); assertTrue(pattern.match(calendar, true));
assertEquals("2022-01-12 00:12:23", DateUtil.date(calendar).toString()); assertEquals("2022-01-12 00:12:23", DateUtil.date(calendar).toString());
} }

View File

@ -0,0 +1,20 @@
package cn.hutool.cron.pattern;
import cn.hutool.core.date.DateTime;
import org.junit.jupiter.api.Test;
import java.util.Date;
public class Issue4006Test {
@Test
void testCron() {
// String cron = "0 0 0 */1 * ?";
String cron = "0 0 0 */1 * ? *";
DateTime judgeTime = DateTime.of(new Date());
CronPattern cronPattern = new CronPattern(cron);
System.out.println("cronPattern = " + cronPattern);
Date nextDate = CronPatternUtil.nextDateAfter(cronPattern, judgeTime, true);
System.out.println("nextDate = " + nextDate);
}
}