mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
fix code
This commit is contained in:
parent
0d3eed0bdd
commit
d0c7b19369
@ -191,7 +191,7 @@ public class CronPattern {
|
||||
/**
|
||||
* 给定时间是否匹配定时任务表达式
|
||||
*
|
||||
* @param fields 时间字段值,{second, minute, hour, dayOfMonth, month, dayOfWeek, year}
|
||||
* @param fields 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
|
||||
* @return 如果匹配返回 {@code true}, 否则返回 {@code false}
|
||||
*/
|
||||
private boolean match(final int[] fields) {
|
||||
@ -206,7 +206,7 @@ public class CronPattern {
|
||||
/**
|
||||
* 获取下一个最近的匹配日期时间
|
||||
*
|
||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, month, dayOfWeek, year}
|
||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
|
||||
* @param zone 时区
|
||||
* @return {@link Calendar},毫秒数为0
|
||||
*/
|
||||
|
@ -29,8 +29,8 @@ public class BoolArrayMatcher implements PartMatcher {
|
||||
/**
|
||||
* 用户定义此字段的最小值
|
||||
*/
|
||||
private final int minValue;
|
||||
private final boolean[] bValues;
|
||||
protected final int minValue;
|
||||
protected final boolean[] bValues;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -50,6 +50,7 @@ public class BoolArrayMatcher implements PartMatcher {
|
||||
|
||||
@Override
|
||||
public boolean test(final Integer value) {
|
||||
final boolean[] bValues = this.bValues;
|
||||
if (null == value || value >= bValues.length) {
|
||||
return false;
|
||||
}
|
||||
@ -58,7 +59,9 @@ public class BoolArrayMatcher implements PartMatcher {
|
||||
|
||||
@Override
|
||||
public int nextAfter(int value) {
|
||||
final int minValue = this.minValue;
|
||||
if(value > minValue){
|
||||
final boolean[] bValues = this.bValues;
|
||||
while(value < bValues.length){
|
||||
if(bValues[value]){
|
||||
return value;
|
||||
|
@ -43,23 +43,72 @@ public class DayOfMonthMatcher extends BoolArrayMatcher {
|
||||
*/
|
||||
public boolean match(final int value, final int month, final boolean isLeapYear) {
|
||||
return (super.test(value) // 在约定日范围内的某一天
|
||||
//匹配器中用户定义了最后一天(31表示最后一天)
|
||||
|| (value > 27 && test(31) && isLastDayOfMonth(value, month, isLeapYear)));
|
||||
//匹配器中用户定义了最后一天(31表示最后一天)
|
||||
|| matchLastDay(value, getLastDay(month, isLeapYear)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为本月最后一天,规则如下:
|
||||
* 获取指定值之后的匹配值,也可以是指定值本身<br>
|
||||
* 如果表达式中存在最后一天(如使用"L"),则:
|
||||
* <ul>
|
||||
* <li>4月、6月、9月、11月最多匹配到30日</li>
|
||||
* <li>4月闰年匹配到29日,非闰年28日</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param value 指定的值
|
||||
* @param month 月份,从1开始
|
||||
* @param isLeapYear 是否为闰年
|
||||
* @return 匹配到的值或之后的值
|
||||
*/
|
||||
public int nextAfter(int value, final int month, final boolean isLeapYear) {
|
||||
final int minValue = this.minValue;
|
||||
if (value > minValue) {
|
||||
final boolean[] bValues = this.bValues;
|
||||
final int lastDay = getLastDay(month, isLeapYear);
|
||||
while (value < lastDay) {
|
||||
if (bValues[value]) {
|
||||
return value;
|
||||
}
|
||||
value++;
|
||||
}
|
||||
|
||||
// value == lastDay
|
||||
if(test(31)){
|
||||
// 匹配当月最后一天
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// 两种情况返回最小值
|
||||
// 一是给定值小于最小值,那下一个匹配值就是最小值
|
||||
// 二是给定值大于最大值,那下一个匹配值也是下一轮的最小值
|
||||
return minValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否匹配本月最后一天,规则如下:
|
||||
* <pre>
|
||||
* 1、闰年2月匹配是否为29
|
||||
* 2、其它月份是否匹配最后一天的日期(可能为30或者31)
|
||||
* 3、表达式包含最后一天(使用31表示)
|
||||
* </pre>
|
||||
*
|
||||
* @param value 被检查的值
|
||||
* @param month 月份,从1开始
|
||||
* @param isLeapYear 是否闰年
|
||||
* @param lastDay 月份的最后一天
|
||||
* @return 是否为本月最后一天
|
||||
*/
|
||||
private static boolean isLastDayOfMonth(final int value, final int month, final boolean isLeapYear) {
|
||||
return value == Month.getLastDay(month - 1, isLeapYear);
|
||||
private boolean matchLastDay(final int value, final int lastDay) {
|
||||
return value > 27 && test(31) && value == lastDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一天
|
||||
*
|
||||
* @param month 月,base1
|
||||
* @param isLeapYear 是否闰年
|
||||
* @return 最后一天
|
||||
*/
|
||||
private static int getLastDay(final int month, final boolean isLeapYear) {
|
||||
return Month.getLastDay(month - 1, isLeapYear);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
package org.dromara.hutool.cron.pattern.matcher;
|
||||
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.cron.pattern.Part;
|
||||
|
||||
import java.time.Year;
|
||||
@ -52,13 +54,13 @@ public class PatternMatcher {
|
||||
final PartMatcher yearMatcher) {
|
||||
|
||||
matchers = new PartMatcher[]{
|
||||
secondMatcher,
|
||||
minuteMatcher,
|
||||
hourMatcher,
|
||||
dayOfMonthMatcher,
|
||||
monthMatcher,
|
||||
dayOfWeekMatcher,
|
||||
yearMatcher
|
||||
secondMatcher,
|
||||
minuteMatcher,
|
||||
hourMatcher,
|
||||
dayOfMonthMatcher,
|
||||
monthMatcher,
|
||||
dayOfWeekMatcher,
|
||||
yearMatcher
|
||||
};
|
||||
}
|
||||
|
||||
@ -109,12 +111,12 @@ public class PatternMatcher {
|
||||
*/
|
||||
private boolean match(final int second, final int minute, final int hour, final int dayOfMonth, final int month, final int dayOfWeek, final int year) {
|
||||
return ((second < 0) || matchers[0].test(second)) // 匹配秒(非秒匹配模式下始终返回true)
|
||||
&& matchers[1].test(minute)// 匹配分
|
||||
&& matchers[2].test(hour)// 匹配时
|
||||
&& matchDayOfMonth(matchers[3], dayOfMonth, month, Year.isLeap(year))// 匹配日
|
||||
&& matchers[4].test(month) // 匹配月
|
||||
&& matchers[5].test(dayOfWeek)// 匹配周
|
||||
&& matchers[6].test(year);// 匹配年
|
||||
&& matchers[1].test(minute)// 匹配分
|
||||
&& matchers[2].test(hour)// 匹配时
|
||||
&& matchDayOfMonth(matchers[3], dayOfMonth, month, Year.isLeap(year))// 匹配日
|
||||
&& matchers[4].test(month) // 匹配月
|
||||
&& matchers[5].test(dayOfWeek)// 匹配周
|
||||
&& matchers[6].test(year);// 匹配年
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,8 +130,8 @@ public class PatternMatcher {
|
||||
*/
|
||||
private static boolean matchDayOfMonth(final PartMatcher matcher, final int dayOfMonth, final int month, final boolean isLeapYear) {
|
||||
return ((matcher instanceof DayOfMonthMatcher) //
|
||||
? ((DayOfMonthMatcher) matcher).match(dayOfMonth, month, isLeapYear) //
|
||||
: matcher.test(dayOfMonth));
|
||||
? ((DayOfMonthMatcher) matcher).match(dayOfMonth, month, isLeapYear) //
|
||||
: matcher.test(dayOfMonth));
|
||||
}
|
||||
//endregion
|
||||
|
||||
@ -145,11 +147,11 @@ public class PatternMatcher {
|
||||
* </ul>
|
||||
*
|
||||
* <pre>
|
||||
* 秒 分 时 日 月 周 年
|
||||
* 秒 分 时 日 月(1) 周(0) 年
|
||||
* 下 <-----------------> 上
|
||||
* </pre>
|
||||
*
|
||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, month, dayOfWeek, year}
|
||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
|
||||
* @param zone 时区
|
||||
* @return {@link Calendar},毫秒数为0
|
||||
*/
|
||||
@ -182,7 +184,7 @@ public class PatternMatcher {
|
||||
* 下 <-----------------> 上
|
||||
* </pre>
|
||||
*
|
||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, month, dayOfWeek, year}
|
||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
|
||||
* @return {@link Calendar},毫秒数为0
|
||||
*/
|
||||
private int[] nextMatchValuesAfter(final int[] values) {
|
||||
@ -197,7 +199,15 @@ public class PatternMatcher {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
nextValue = matchers[i].nextAfter(values[i]);
|
||||
|
||||
if (i == Part.DAY_OF_MONTH.ordinal()) {
|
||||
final boolean isLeapYear = DateUtil.isLeapYear(newValues[Part.YEAR.ordinal()]);
|
||||
final int month = values[Part.MONTH.ordinal()];
|
||||
nextValue = ((DayOfMonthMatcher) matchers[i]).nextAfter(values[i], month, isLeapYear);
|
||||
} else {
|
||||
nextValue = matchers[i].nextAfter(values[i]);
|
||||
}
|
||||
|
||||
if (nextValue > values[i]) {
|
||||
// 此部分正常获取新值,结束循环,后续的部分置最小值
|
||||
newValues[i] = nextValue;
|
||||
@ -209,6 +219,7 @@ public class PatternMatcher {
|
||||
nextValue = -1;// 标记回退查找
|
||||
break;
|
||||
}
|
||||
|
||||
// 值不变,检查下一个部分
|
||||
i--;
|
||||
}
|
||||
@ -221,7 +232,15 @@ public class PatternMatcher {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
nextValue = matchers[i].nextAfter(values[i] + 1);
|
||||
|
||||
if (i == Part.DAY_OF_MONTH.ordinal()) {
|
||||
final boolean isLeapYear = DateUtil.isLeapYear(newValues[Part.YEAR.ordinal()]);
|
||||
final int month = values[Part.MONTH.ordinal()];
|
||||
nextValue = ((DayOfMonthMatcher) matchers[i]).nextAfter(values[i] + 1, month, isLeapYear);
|
||||
} else {
|
||||
nextValue = matchers[i].nextAfter(values[i] + 1);
|
||||
}
|
||||
|
||||
if (nextValue > values[i]) {
|
||||
newValues[i] = nextValue;
|
||||
i--;
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.cron.pattern;
|
||||
|
||||
import org.dromara.hutool.core.date.DateTime;
|
||||
import org.dromara.hutool.core.date.DateUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
public class IssueI92H5HTest {
|
||||
@Test
|
||||
void nextMatchAfterTest() {
|
||||
// 匹配所有月,返回下一月
|
||||
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());
|
||||
System.out.println(DateUtil.date(calendar));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user