mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -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}
|
* @return 如果匹配返回 {@code true}, 否则返回 {@code false}
|
||||||
*/
|
*/
|
||||||
private boolean match(final int[] fields) {
|
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 时区
|
* @param zone 时区
|
||||||
* @return {@link Calendar},毫秒数为0
|
* @return {@link Calendar},毫秒数为0
|
||||||
*/
|
*/
|
||||||
|
@@ -29,8 +29,8 @@ public class BoolArrayMatcher implements PartMatcher {
|
|||||||
/**
|
/**
|
||||||
* 用户定义此字段的最小值
|
* 用户定义此字段的最小值
|
||||||
*/
|
*/
|
||||||
private final int minValue;
|
protected final int minValue;
|
||||||
private final boolean[] bValues;
|
protected final boolean[] bValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
@@ -50,6 +50,7 @@ public class BoolArrayMatcher implements PartMatcher {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(final Integer value) {
|
public boolean test(final Integer value) {
|
||||||
|
final boolean[] bValues = this.bValues;
|
||||||
if (null == value || value >= bValues.length) {
|
if (null == value || value >= bValues.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -58,7 +59,9 @@ public class BoolArrayMatcher implements PartMatcher {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int nextAfter(int value) {
|
public int nextAfter(int value) {
|
||||||
|
final int minValue = this.minValue;
|
||||||
if(value > minValue){
|
if(value > minValue){
|
||||||
|
final boolean[] bValues = this.bValues;
|
||||||
while(value < bValues.length){
|
while(value < bValues.length){
|
||||||
if(bValues[value]){
|
if(bValues[value]){
|
||||||
return value;
|
return value;
|
||||||
|
@@ -43,23 +43,72 @@ public class DayOfMonthMatcher extends BoolArrayMatcher {
|
|||||||
*/
|
*/
|
||||||
public boolean match(final int value, final int month, final boolean isLeapYear) {
|
public boolean match(final int value, final int month, final boolean isLeapYear) {
|
||||||
return (super.test(value) // 在约定日范围内的某一天
|
return (super.test(value) // 在约定日范围内的某一天
|
||||||
//匹配器中用户定义了最后一天(31表示最后一天)
|
//匹配器中用户定义了最后一天(31表示最后一天)
|
||||||
|| (value > 27 && test(31) && isLastDayOfMonth(value, month, isLeapYear)));
|
|| 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>
|
* <pre>
|
||||||
* 1、闰年2月匹配是否为29
|
* 1、闰年2月匹配是否为29
|
||||||
* 2、其它月份是否匹配最后一天的日期(可能为30或者31)
|
* 2、其它月份是否匹配最后一天的日期(可能为30或者31)
|
||||||
|
* 3、表达式包含最后一天(使用31表示)
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param value 被检查的值
|
* @param value 被检查的值
|
||||||
* @param month 月份,从1开始
|
* @param lastDay 月份的最后一天
|
||||||
* @param isLeapYear 是否闰年
|
|
||||||
* @return 是否为本月最后一天
|
* @return 是否为本月最后一天
|
||||||
*/
|
*/
|
||||||
private static boolean isLastDayOfMonth(final int value, final int month, final boolean isLeapYear) {
|
private boolean matchLastDay(final int value, final int lastDay) {
|
||||||
return value == Month.getLastDay(month - 1, isLeapYear);
|
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;
|
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 org.dromara.hutool.cron.pattern.Part;
|
||||||
|
|
||||||
import java.time.Year;
|
import java.time.Year;
|
||||||
@@ -52,13 +54,13 @@ public class PatternMatcher {
|
|||||||
final PartMatcher yearMatcher) {
|
final PartMatcher yearMatcher) {
|
||||||
|
|
||||||
matchers = new PartMatcher[]{
|
matchers = new PartMatcher[]{
|
||||||
secondMatcher,
|
secondMatcher,
|
||||||
minuteMatcher,
|
minuteMatcher,
|
||||||
hourMatcher,
|
hourMatcher,
|
||||||
dayOfMonthMatcher,
|
dayOfMonthMatcher,
|
||||||
monthMatcher,
|
monthMatcher,
|
||||||
dayOfWeekMatcher,
|
dayOfWeekMatcher,
|
||||||
yearMatcher
|
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) {
|
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)
|
return ((second < 0) || matchers[0].test(second)) // 匹配秒(非秒匹配模式下始终返回true)
|
||||||
&& matchers[1].test(minute)// 匹配分
|
&& matchers[1].test(minute)// 匹配分
|
||||||
&& matchers[2].test(hour)// 匹配时
|
&& matchers[2].test(hour)// 匹配时
|
||||||
&& matchDayOfMonth(matchers[3], dayOfMonth, month, Year.isLeap(year))// 匹配日
|
&& matchDayOfMonth(matchers[3], dayOfMonth, month, Year.isLeap(year))// 匹配日
|
||||||
&& matchers[4].test(month) // 匹配月
|
&& matchers[4].test(month) // 匹配月
|
||||||
&& matchers[5].test(dayOfWeek)// 匹配周
|
&& matchers[5].test(dayOfWeek)// 匹配周
|
||||||
&& matchers[6].test(year);// 匹配年
|
&& 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) {
|
private static boolean matchDayOfMonth(final PartMatcher matcher, final int dayOfMonth, final int month, final boolean isLeapYear) {
|
||||||
return ((matcher instanceof DayOfMonthMatcher) //
|
return ((matcher instanceof DayOfMonthMatcher) //
|
||||||
? ((DayOfMonthMatcher) matcher).match(dayOfMonth, month, isLeapYear) //
|
? ((DayOfMonthMatcher) matcher).match(dayOfMonth, month, isLeapYear) //
|
||||||
: matcher.test(dayOfMonth));
|
: matcher.test(dayOfMonth));
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
@@ -145,11 +147,11 @@ public class PatternMatcher {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* 秒 分 时 日 月 周 年
|
* 秒 分 时 日 月(1) 周(0) 年
|
||||||
* 下 <-----------------> 上
|
* 下 <-----------------> 上
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, month, dayOfWeek, year}
|
* @param values 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
|
||||||
* @param zone 时区
|
* @param zone 时区
|
||||||
* @return {@link Calendar},毫秒数为0
|
* @return {@link Calendar},毫秒数为0
|
||||||
*/
|
*/
|
||||||
@@ -182,7 +184,7 @@ public class PatternMatcher {
|
|||||||
* 下 <-----------------> 上
|
* 下 <-----------------> 上
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param values 时间字段值,{second, minute, hour, dayOfMonth, month, dayOfWeek, year}
|
* @param values 时间字段值,{second, minute, hour, dayOfMonth, monthBase1, dayOfWeekBase0, year}
|
||||||
* @return {@link Calendar},毫秒数为0
|
* @return {@link Calendar},毫秒数为0
|
||||||
*/
|
*/
|
||||||
private int[] nextMatchValuesAfter(final int[] values) {
|
private int[] nextMatchValuesAfter(final int[] values) {
|
||||||
@@ -197,7 +199,15 @@ public class PatternMatcher {
|
|||||||
i--;
|
i--;
|
||||||
continue;
|
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]) {
|
if (nextValue > values[i]) {
|
||||||
// 此部分正常获取新值,结束循环,后续的部分置最小值
|
// 此部分正常获取新值,结束循环,后续的部分置最小值
|
||||||
newValues[i] = nextValue;
|
newValues[i] = nextValue;
|
||||||
@@ -209,6 +219,7 @@ public class PatternMatcher {
|
|||||||
nextValue = -1;// 标记回退查找
|
nextValue = -1;// 标记回退查找
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 值不变,检查下一个部分
|
// 值不变,检查下一个部分
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
@@ -221,7 +232,15 @@ public class PatternMatcher {
|
|||||||
i++;
|
i++;
|
||||||
continue;
|
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]) {
|
if (nextValue > values[i]) {
|
||||||
newValues[i] = nextValue;
|
newValues[i] = nextValue;
|
||||||
i--;
|
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));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user