mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
6427d6fb13
commit
2dde8d18d0
@ -151,7 +151,7 @@ public class CronPattern {
|
||||
final int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 星期从0开始,0和7都表示周日
|
||||
final int year = calendar.get(Calendar.YEAR);
|
||||
|
||||
return nextMatchAfter(second, minute, hour, dayOfMonth, month, dayOfWeek, year, calendar.getTimeZone());
|
||||
return nextMatchAfter(new int[]{second, minute, hour, dayOfMonth, month, dayOfWeek, year}, calendar.getTimeZone());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,23 +183,16 @@ public class CronPattern {
|
||||
/**
|
||||
* 获取下一个最近的匹配日期时间
|
||||
*
|
||||
* @param second 秒
|
||||
* @param minute 分
|
||||
* @param hour 时
|
||||
* @param dayOfMonth 天
|
||||
* @param month 月(从1开始)
|
||||
* @param dayOfWeek 周(从0开始, 0表示周日)
|
||||
* @param year 年
|
||||
* @param values 时间字段值
|
||||
* @param zone 时区
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
private Calendar nextMatchAfter(int second, int minute, int hour, int dayOfMonth, int month, int dayOfWeek, int year, TimeZone zone) {
|
||||
List<Calendar> nextMatchs = new ArrayList<>(second);
|
||||
private Calendar nextMatchAfter(int[] values, TimeZone zone) {
|
||||
final List<Calendar> nextMatches = new ArrayList<>(matchers.size());
|
||||
for (PatternMatcher matcher : matchers) {
|
||||
nextMatchs.add(matcher.nextMatchAfter(
|
||||
second, minute, hour, dayOfMonth, month, dayOfWeek, year, zone));
|
||||
nextMatches.add(matcher.nextMatchAfter(values, zone));
|
||||
}
|
||||
// 返回匹配到的最早日期
|
||||
return CollUtil.min(nextMatchs);
|
||||
return CollUtil.min(nextMatches);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import cn.hutool.core.date.Week;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.cron.CronException;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* 表达式各个部分的枚举,用于限定在表达式中的位置和规则(如最小值和最大值)<br>
|
||||
* {@link #ordinal()}表示此部分在表达式中的位置,如0表示秒<br>
|
||||
@ -18,24 +20,30 @@ import cn.hutool.cron.CronException;
|
||||
* @since 5.8.0
|
||||
*/
|
||||
public enum Part {
|
||||
SECOND(0, 59),
|
||||
MINUTE(0, 59),
|
||||
HOUR(0, 23),
|
||||
DAY_OF_MONTH(1, 31),
|
||||
MONTH(Month.JANUARY.getValueBaseOne(), Month.DECEMBER.getValueBaseOne()),
|
||||
DAY_OF_WEEK(Week.SUNDAY.ordinal(), Week.SATURDAY.ordinal()),
|
||||
YEAR(1970, 2099);
|
||||
SECOND(Calendar.SECOND, 0, 59),
|
||||
MINUTE(Calendar.MINUTE, 0, 59),
|
||||
HOUR(Calendar.HOUR_OF_DAY, 0, 23),
|
||||
DAY_OF_MONTH(Calendar.DAY_OF_MONTH, 1, 31),
|
||||
MONTH(Calendar.MONTH, Month.JANUARY.getValueBaseOne(), Month.DECEMBER.getValueBaseOne()),
|
||||
DAY_OF_WEEK(Calendar.DAY_OF_WEEK, Week.SUNDAY.ordinal(), Week.SATURDAY.ordinal()),
|
||||
YEAR(Calendar.YEAR, 1970, 2099);
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
private static final Part[] ENUMS = Part.values();
|
||||
|
||||
private final int calendarField;
|
||||
private final int min;
|
||||
private final int max;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param min 限定最小值(包含)
|
||||
* @param max 限定最大值(包含)
|
||||
* @param calendarField Calendar中对应字段项
|
||||
* @param min 限定最小值(包含)
|
||||
* @param max 限定最大值(包含)
|
||||
*/
|
||||
Part(int min, int max) {
|
||||
Part(int calendarField, int min, int max) {
|
||||
this.calendarField = calendarField;
|
||||
if (min > max) {
|
||||
this.min = max;
|
||||
this.max = min;
|
||||
@ -45,6 +53,15 @@ public enum Part {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Calendar中对应字段项
|
||||
*
|
||||
* @return Calendar中对应字段项
|
||||
*/
|
||||
public int getCalendarField() {
|
||||
return this.calendarField;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最小值
|
||||
*
|
||||
@ -75,4 +92,14 @@ public enum Part {
|
||||
() -> new CronException("Value {} out of range: [{} , {}]", value, min, max));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据位置获取Part
|
||||
*
|
||||
* @param i 位置,从0开始
|
||||
* @return Part
|
||||
*/
|
||||
public static Part of(int i) {
|
||||
return ENUMS[i];
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.hutool.cron.pattern.matcher;
|
||||
|
||||
import cn.hutool.core.lang.mutable.MutableBool;
|
||||
import cn.hutool.cron.pattern.Part;
|
||||
|
||||
import java.time.Year;
|
||||
@ -106,79 +105,108 @@ public class PatternMatcher {
|
||||
/**
|
||||
* 获取下一个匹配日期时间
|
||||
*
|
||||
* @param second 秒
|
||||
* @param minute 分
|
||||
* @param hour 时
|
||||
* @param dayOfMonth 天
|
||||
* @param month 月(从1开始)
|
||||
* @param dayOfWeek 周(从0开始, 0表示周日)
|
||||
* @param year 年
|
||||
* @param zone 时区
|
||||
* @param values 时间字段值
|
||||
* @param zone 时区
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public Calendar nextMatchAfter(int second, int minute, int hour,
|
||||
int dayOfMonth, int month, int dayOfWeek, int year, TimeZone zone) {
|
||||
public Calendar nextMatchAfter(int[] values, TimeZone zone) {
|
||||
|
||||
Calendar calendar = Calendar.getInstance(zone);
|
||||
|
||||
// 上一个字段不一致,说明产生了新值,下一个字段使用最小值
|
||||
MutableBool isNextEquals = new MutableBool(true);
|
||||
// 年
|
||||
final int nextYear = nextAfter(get(Part.YEAR), year, isNextEquals);
|
||||
calendar.set(Calendar.YEAR, nextYear);
|
||||
int i = Part.YEAR.ordinal();
|
||||
int nextValue = 0;
|
||||
while (i >= 0) {
|
||||
nextValue = matchers[i].nextAfter(values[i]);
|
||||
if (nextValue > values[i]) {
|
||||
// 此部分正常获取新值,结束循环,后续的部分置最小值
|
||||
setValue(calendar, Part.of(i), nextValue);
|
||||
i--;
|
||||
break;
|
||||
} else if (nextValue < values[i]) {
|
||||
// 此部分下一个值获取到的值产生回退,回到上一个部分,继续获取新值
|
||||
i++;
|
||||
nextValue = -1;// 标记回退查找
|
||||
break;
|
||||
}
|
||||
// 值不变,设置后检查下一个部分
|
||||
setValue(calendar, Part.of(i), nextValue);
|
||||
i--;
|
||||
}
|
||||
|
||||
// 周
|
||||
final int nextDayOfWeek = nextAfter(get(Part.DAY_OF_WEEK), dayOfWeek, isNextEquals);
|
||||
calendar.set(Calendar.DAY_OF_WEEK, nextDayOfWeek + 1);
|
||||
// 值产生回退,向上查找变更值
|
||||
if(-1 == nextValue){
|
||||
while(i <= Part.YEAR.ordinal()){
|
||||
nextValue = matchers[i].nextAfter(values[i] + 1);
|
||||
if(nextValue > values[i]){
|
||||
setValue(calendar, Part.of(i), nextValue);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// 月
|
||||
final int nextMonth = nextAfter(get(Part.MONTH), month, isNextEquals);
|
||||
calendar.set(Calendar.MONTH, nextMonth - 1);
|
||||
|
||||
// 日
|
||||
final int nextDayOfMonth = nextAfter(get(Part.DAY_OF_MONTH), dayOfMonth, isNextEquals);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, nextDayOfMonth);
|
||||
|
||||
// 时
|
||||
final int nextHour = nextAfter(get(Part.HOUR), hour, isNextEquals);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, nextHour);
|
||||
|
||||
// 分
|
||||
int nextMinute = nextAfter(get(Part.MINUTE), minute, isNextEquals);
|
||||
calendar.set(Calendar.MINUTE, nextMinute);
|
||||
|
||||
// 秒
|
||||
final int nextSecond = nextAfter(get(Part.SECOND), second, isNextEquals);
|
||||
calendar.set(Calendar.SECOND, nextSecond);
|
||||
// 修改值以下的字段全部归最小值
|
||||
setToMin(calendar, i);
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应字段匹配器的下一个值
|
||||
* 设置从{@link Part#SECOND}到指定部分,全部设置为最小值
|
||||
*
|
||||
* @param matcher 匹配器
|
||||
* @param value 值
|
||||
* @param isNextEquals 是否下一个值和值相同。不同获取初始值,相同获取下一值,然后修改。
|
||||
* @return 下一个值,-1标识匹配所有值的情况,应获取整个字段的最小值
|
||||
* @param calendar {@link Calendar}
|
||||
* @param toPart 截止的部分
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
private static int nextAfter(PartMatcher matcher, int value, MutableBool isNextEquals) {
|
||||
int nextValue;
|
||||
if (isNextEquals.get()) {
|
||||
// 上一层级得到相同值,下级获取下个值
|
||||
nextValue = matcher.nextAfter(value);
|
||||
isNextEquals.set(nextValue == value);
|
||||
} else {
|
||||
// 上一层级的值得到了不同值,下级的所有值使用最小值
|
||||
if (matcher instanceof AlwaysTrueMatcher) {
|
||||
nextValue = value;
|
||||
} else if (matcher instanceof BoolArrayMatcher) {
|
||||
nextValue = ((BoolArrayMatcher) matcher).getMinValue();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid matcher: " + matcher.getClass().getName());
|
||||
}
|
||||
private Calendar setToMin(Calendar calendar, int toPart) {
|
||||
Part part;
|
||||
for (int i = 0; i <= toPart; i++) {
|
||||
part = Part.of(i);
|
||||
setValue(calendar, part, getMin(part));
|
||||
}
|
||||
return nextValue;
|
||||
return calendar;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表达式部分的最小值
|
||||
*
|
||||
* @param part {@link Part}
|
||||
* @return 最小值,如果匹配所有,返回对应部分范围的最小值
|
||||
*/
|
||||
private int getMin(Part part) {
|
||||
PartMatcher matcher = get(part);
|
||||
|
||||
int min;
|
||||
if (matcher instanceof AlwaysTrueMatcher) {
|
||||
min = part.getMin();
|
||||
} else if (matcher instanceof BoolArrayMatcher) {
|
||||
min = ((BoolArrayMatcher) matcher).getMinValue();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid matcher: " + matcher.getClass().getName());
|
||||
}
|
||||
return min;
|
||||
}
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* 设置对应部分修正后的值
|
||||
* @param calendar {@link Calendar}
|
||||
* @param part 表达式部分
|
||||
* @param value 值
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
private Calendar setValue(Calendar calendar, Part part, int value){
|
||||
switch (part){
|
||||
case MONTH:
|
||||
value -= 1;
|
||||
break;
|
||||
case DAY_OF_WEEK:
|
||||
value += 1;
|
||||
break;
|
||||
}
|
||||
//noinspection MagicConstant
|
||||
calendar.set(part.getCalendarField(), value);
|
||||
return calendar;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package cn.hutool.cron.pattern;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.Week;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Calendar;
|
||||
@ -14,20 +11,27 @@ public class CronPatternNextMatchTest {
|
||||
@Test
|
||||
public void nextMatchAfterTest(){
|
||||
CronPattern pattern = new CronPattern("23 12 * 12 * * *");
|
||||
|
||||
// 时间正常递增
|
||||
//noinspection ConstantConditions
|
||||
final Calendar calendar = pattern.nextMatchAfter(
|
||||
DateUtil.parse("2022-04-12 09:12:24").toCalendar());
|
||||
Calendar calendar = pattern.nextMatchAfter(
|
||||
DateUtil.parse("2022-04-12 09:12:12").toCalendar());
|
||||
|
||||
Console.log(DateUtil.date(calendar));
|
||||
Assert.assertTrue(pattern.match(calendar, true));
|
||||
}
|
||||
Assert.assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString());
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void calendarTest(){
|
||||
final Calendar ca = Calendar.getInstance();
|
||||
ca.set(Calendar.DAY_OF_WEEK, Week.SATURDAY.getValue());
|
||||
// 秒超出规定值的最大值,小时+1
|
||||
//noinspection ConstantConditions
|
||||
calendar = pattern.nextMatchAfter(
|
||||
DateUtil.parse("2022-04-12 09:12:24").toCalendar());
|
||||
Assert.assertTrue(pattern.match(calendar, true));
|
||||
Assert.assertEquals("2022-04-12 10:12:23", DateUtil.date(calendar).toString());
|
||||
|
||||
Console.log(DateUtil.date(ca));
|
||||
// 天超出规定值的最大值,月+1
|
||||
//noinspection ConstantConditions
|
||||
calendar = pattern.nextMatchAfter(
|
||||
DateUtil.parse("2022-04-13 09:12:24").toCalendar());
|
||||
Assert.assertTrue(pattern.match(calendar, true));
|
||||
Assert.assertEquals("2022-05-12 00:12:23", DateUtil.date(calendar).toString());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user