This commit is contained in:
Looly 2025-09-05 17:23:06 +08:00
parent 175dd746ac
commit b6e7287287
9 changed files with 79 additions and 28 deletions

View File

@ -97,7 +97,12 @@ public class AnnotationUtil {
// region ----- getAnnotation
/**
* 获取直接声明的注解若已有缓存则从缓存中获取
* 获取直接声明的注解若已有缓存则从缓存中获取主要为
* <ul>
* <li>只返回直接声明在该元素上的注解</li>
* <li>不包括从父类或接口继承来的注解</li>
* <li>只获取当前类/方法/字段等自身定义的注解</li>
* </ul>
*
* @param element {@link AnnotatedElement}
* @return 注解
@ -108,7 +113,12 @@ public class AnnotationUtil {
}
/**
* 获取指定注解
* 获取指定注解主要为:
* <ul>
* <li>返回该元素上的所有注解</li>
* <li>包括从父类或接口继承来的注解</li>
* <li>获取当前元素以及继承自父类或接口的所有注解</li>
* </ul>
*
* @param annotationEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param isToCombination 是否为转换为组合注解组合注解可以递归获取注解的注解

View File

@ -342,8 +342,7 @@ public class HierarchicalAnnotatedElements implements AnnotatedElement, Iterable
scanHierarchy(mappings, (Class<?>)source, false, source);
}
// 原始元素是方法
else if (source instanceof Method) {
final Method methodSource = (Method)source;
else if (source instanceof final Method methodSource) {
// 静态私有与被final关键字修饰方法无法被子类重写因此不可能具有层级结构
if (Modifier.isPrivate(methodSource.getModifiers())
|| Modifier.isFinal(methodSource.getModifiers())

View File

@ -276,14 +276,14 @@ public enum Month {
/**
* 获得指定月的最后一天
*
* @param month 月份从0开始
* @param monthBase0 月份从0开始
* @param isLeapYear 是否为闰年闰年只对二月有影响
* @return 最后一天可能为28,29,30,31
* @since 5.4.7
*/
public static int getLastDay(final int month, final boolean isLeapYear) {
final Month of = of(month);
Assert.notNull(of, "Invalid Month base 0: " + month);
public static int getLastDay(final int monthBase0, final boolean isLeapYear) {
final Month of = of(monthBase0);
Assert.notNull(of, "Invalid Month base 0: " + monthBase0);
return of.getLastDay(isLeapYear);
}

View File

@ -18,6 +18,7 @@ package cn.hutool.v7.cron.pattern;
import cn.hutool.v7.core.comparator.CompareUtil;
import cn.hutool.v7.core.date.CalendarUtil;
import cn.hutool.v7.core.lang.Console;
import cn.hutool.v7.cron.pattern.matcher.PatternMatcher;
import cn.hutool.v7.cron.pattern.parser.PatternParser;

View File

@ -40,7 +40,7 @@ public class DayOfMonthMatcher extends BoolArrayMatcher {
/**
* 给定的日期是否匹配当前匹配器
*
* @param value 被检查的值此处为日
* @param value 被检查的值此处为日从1开始
* @param month 实际的月份从1开始
* @param isLeapYear 是否闰年
* @return 是否匹配

View File

@ -17,10 +17,10 @@
package cn.hutool.v7.cron.pattern.matcher;
import cn.hutool.v7.core.date.DateUtil;
import cn.hutool.v7.core.text.StrUtil;
import cn.hutool.v7.cron.pattern.Part;
import java.time.Year;
import java.util.Arrays;
import java.util.Calendar;
import java.util.TimeZone;
@ -177,9 +177,15 @@ public class PatternMatcher {
@Override
public String toString() {
return "PatternMatcher{" +
"matchers=" + Arrays.toString(matchers) +
'}';
return StrUtil.format("""
SECOND : {}
MINUTE : {}
HOUR : {}
DAY_OF_MONTH: {}
MONTH : {}
DAY_OF_WEEK : {}
YEAR : {}
""", (Object[]) this.matchers);
}
/**

View File

@ -29,6 +29,11 @@ public class YearValueMatcher implements PartMatcher {
private final LinkedHashSet<Integer> valueList;
/**
* 构造
*
* @param intValueList 年数字列表
*/
public YearValueMatcher(final Collection<Integer> intValueList) {
this.valueList = new LinkedHashSet<>(intValueList);
}
@ -49,4 +54,11 @@ public class YearValueMatcher implements PartMatcher {
// 年无效此表达式整体无效
return -1;
}
@Override
public String toString() {
return "YearValueMatcher{" +
"valueList=" + valueList +
'}';
}
}

View File

@ -91,14 +91,11 @@ public class PartParser {
throw new CronException("Invalid part value: [{}]", value);
}
switch (this.part) {
case DAY_OF_MONTH:
return new DayOfMonthMatcher(values);
case YEAR:
return new YearValueMatcher(values);
default:
return new BoolArrayMatcher(values);
}
return switch (this.part) {
case DAY_OF_MONTH -> new DayOfMonthMatcher(values);
case YEAR -> new YearValueMatcher(values);
default -> new BoolArrayMatcher(values);
};
}
/**
@ -163,6 +160,7 @@ public class PartParser {
* <li>8-3</li>
* <li>3-3</li>
* </ul>
* 其中"*"解析时按照min值处理
*
* @param value 范围表达式
* @param step 步进
@ -287,15 +285,15 @@ public class PartParser {
return part.getMax();
}
switch (this.part) {
case MONTH:
return switch (this.part) {
case MONTH ->
// 月份从1开始
return Month.of(name).getValueBaseOne();
case DAY_OF_WEEK:
Month.of(name).getValueBaseOne();
case DAY_OF_WEEK ->
// 周从0开始0表示周日
return Week.of(name).ordinal();
}
Week.of(name).ordinal();
default -> throw new CronException("Invalid alias value: [{}]", name);
};
throw new CronException("Invalid alias value: [{}]", name);
}
}

View File

@ -16,6 +16,7 @@
package cn.hutool.v7.cron.pattern;
import cn.hutool.v7.core.date.DateTime;
import cn.hutool.v7.core.date.DateUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -60,4 +61,28 @@ public class CronPatternUtilTest {
Assertions.assertEquals("2018-10-31 03:00:00", matchedDates.get(3).toString());
Assertions.assertEquals("2018-10-31 04:00:00", matchedDates.get(4).toString());
}
@Test
public void issue4056Test() {
// "*/5""1/5"意义相同从1号开始每5天一个匹配则匹配的天为
// 2025-02-01, 2025-02-06, 2025-02-11, 2025-02-16, 2025-02-21, 2025-02-26
// 2025-02-28不应该在匹配之列
final String cron = "0 0 0 */5 * ? *";
final CronPattern cronPattern = new CronPattern(cron);
final boolean match = cronPattern.match(DateUtil.parse("2025-02-28 00:00:00").toCalendar(), true);
Assertions.assertFalse( match);
}
@Test
public void issue4056Test2() {
final String cron = "0 0 0 */5 * ? *";
final CronPattern cronPattern = new CronPattern(cron);
final DateTime judgeTime = DateUtil.parse("2025-02-27 23:59:59");
final Date nextDate = CronPatternUtil.nextDateAfter(cronPattern, judgeTime);
// "*/5""1/5"意义相同从1号开始每5天一个匹配则匹配的天为
// 2025-02-01, 2025-02-06, 2025-02-11, 2025-02-16, 2025-02-21, 2025-02-26
// 下一个匹配日期应为2025-03-01
Assertions.assertEquals("2025-03-01 00:00:00", nextDate.toString());
}
}