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 dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 星期从0开始,0和7都表示周日
|
||||||
final int year = calendar.get(Calendar.YEAR);
|
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
|
@Override
|
||||||
@ -183,23 +183,16 @@ public class CronPattern {
|
|||||||
/**
|
/**
|
||||||
* 获取下一个最近的匹配日期时间
|
* 获取下一个最近的匹配日期时间
|
||||||
*
|
*
|
||||||
* @param second 秒
|
* @param values 时间字段值
|
||||||
* @param minute 分
|
|
||||||
* @param hour 时
|
|
||||||
* @param dayOfMonth 天
|
|
||||||
* @param month 月(从1开始)
|
|
||||||
* @param dayOfWeek 周(从0开始, 0表示周日)
|
|
||||||
* @param year 年
|
|
||||||
* @param zone 时区
|
* @param zone 时区
|
||||||
* @return {@link Calendar}
|
* @return {@link Calendar}
|
||||||
*/
|
*/
|
||||||
private Calendar nextMatchAfter(int second, int minute, int hour, int dayOfMonth, int month, int dayOfWeek, int year, TimeZone zone) {
|
private Calendar nextMatchAfter(int[] values, TimeZone zone) {
|
||||||
List<Calendar> nextMatchs = new ArrayList<>(second);
|
final List<Calendar> nextMatches = new ArrayList<>(matchers.size());
|
||||||
for (PatternMatcher matcher : matchers) {
|
for (PatternMatcher matcher : matchers) {
|
||||||
nextMatchs.add(matcher.nextMatchAfter(
|
nextMatches.add(matcher.nextMatchAfter(values, zone));
|
||||||
second, minute, hour, dayOfMonth, month, dayOfWeek, year, 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.core.lang.Assert;
|
||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表达式各个部分的枚举,用于限定在表达式中的位置和规则(如最小值和最大值)<br>
|
* 表达式各个部分的枚举,用于限定在表达式中的位置和规则(如最小值和最大值)<br>
|
||||||
* {@link #ordinal()}表示此部分在表达式中的位置,如0表示秒<br>
|
* {@link #ordinal()}表示此部分在表达式中的位置,如0表示秒<br>
|
||||||
@ -18,24 +20,30 @@ import cn.hutool.cron.CronException;
|
|||||||
* @since 5.8.0
|
* @since 5.8.0
|
||||||
*/
|
*/
|
||||||
public enum Part {
|
public enum Part {
|
||||||
SECOND(0, 59),
|
SECOND(Calendar.SECOND, 0, 59),
|
||||||
MINUTE(0, 59),
|
MINUTE(Calendar.MINUTE, 0, 59),
|
||||||
HOUR(0, 23),
|
HOUR(Calendar.HOUR_OF_DAY, 0, 23),
|
||||||
DAY_OF_MONTH(1, 31),
|
DAY_OF_MONTH(Calendar.DAY_OF_MONTH, 1, 31),
|
||||||
MONTH(Month.JANUARY.getValueBaseOne(), Month.DECEMBER.getValueBaseOne()),
|
MONTH(Calendar.MONTH, Month.JANUARY.getValueBaseOne(), Month.DECEMBER.getValueBaseOne()),
|
||||||
DAY_OF_WEEK(Week.SUNDAY.ordinal(), Week.SATURDAY.ordinal()),
|
DAY_OF_WEEK(Calendar.DAY_OF_WEEK, Week.SUNDAY.ordinal(), Week.SATURDAY.ordinal()),
|
||||||
YEAR(1970, 2099);
|
YEAR(Calendar.YEAR, 1970, 2099);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
private static final Part[] ENUMS = Part.values();
|
||||||
|
|
||||||
|
private final int calendarField;
|
||||||
private final int min;
|
private final int min;
|
||||||
private final int max;
|
private final int max;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param min 限定最小值(包含)
|
* @param calendarField Calendar中对应字段项
|
||||||
* @param max 限定最大值(包含)
|
* @param min 限定最小值(包含)
|
||||||
|
* @param max 限定最大值(包含)
|
||||||
*/
|
*/
|
||||||
Part(int min, int max) {
|
Part(int calendarField, int min, int max) {
|
||||||
|
this.calendarField = calendarField;
|
||||||
if (min > max) {
|
if (min > max) {
|
||||||
this.min = max;
|
this.min = max;
|
||||||
this.max = min;
|
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));
|
() -> new CronException("Value {} out of range: [{} , {}]", value, min, max));
|
||||||
return value;
|
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;
|
package cn.hutool.cron.pattern.matcher;
|
||||||
|
|
||||||
import cn.hutool.core.lang.mutable.MutableBool;
|
|
||||||
import cn.hutool.cron.pattern.Part;
|
import cn.hutool.cron.pattern.Part;
|
||||||
|
|
||||||
import java.time.Year;
|
import java.time.Year;
|
||||||
@ -106,79 +105,108 @@ public class PatternMatcher {
|
|||||||
/**
|
/**
|
||||||
* 获取下一个匹配日期时间
|
* 获取下一个匹配日期时间
|
||||||
*
|
*
|
||||||
* @param second 秒
|
* @param values 时间字段值
|
||||||
* @param minute 分
|
* @param zone 时区
|
||||||
* @param hour 时
|
|
||||||
* @param dayOfMonth 天
|
|
||||||
* @param month 月(从1开始)
|
|
||||||
* @param dayOfWeek 周(从0开始, 0表示周日)
|
|
||||||
* @param year 年
|
|
||||||
* @param zone 时区
|
|
||||||
* @return {@link Calendar}
|
* @return {@link Calendar}
|
||||||
*/
|
*/
|
||||||
public Calendar nextMatchAfter(int second, int minute, int hour,
|
public Calendar nextMatchAfter(int[] values, TimeZone zone) {
|
||||||
int dayOfMonth, int month, int dayOfWeek, int year, TimeZone zone) {
|
|
||||||
|
|
||||||
Calendar calendar = Calendar.getInstance(zone);
|
Calendar calendar = Calendar.getInstance(zone);
|
||||||
|
|
||||||
// 上一个字段不一致,说明产生了新值,下一个字段使用最小值
|
int i = Part.YEAR.ordinal();
|
||||||
MutableBool isNextEquals = new MutableBool(true);
|
int nextValue = 0;
|
||||||
// 年
|
while (i >= 0) {
|
||||||
final int nextYear = nextAfter(get(Part.YEAR), year, isNextEquals);
|
nextValue = matchers[i].nextAfter(values[i]);
|
||||||
calendar.set(Calendar.YEAR, nextYear);
|
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);
|
if(-1 == nextValue){
|
||||||
calendar.set(Calendar.DAY_OF_WEEK, nextDayOfWeek + 1);
|
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);
|
setToMin(calendar, i);
|
||||||
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);
|
|
||||||
|
|
||||||
return calendar;
|
return calendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取对应字段匹配器的下一个值
|
* 设置从{@link Part#SECOND}到指定部分,全部设置为最小值
|
||||||
*
|
*
|
||||||
* @param matcher 匹配器
|
* @param calendar {@link Calendar}
|
||||||
* @param value 值
|
* @param toPart 截止的部分
|
||||||
* @param isNextEquals 是否下一个值和值相同。不同获取初始值,相同获取下一值,然后修改。
|
* @return {@link Calendar}
|
||||||
* @return 下一个值,-1标识匹配所有值的情况,应获取整个字段的最小值
|
|
||||||
*/
|
*/
|
||||||
private static int nextAfter(PartMatcher matcher, int value, MutableBool isNextEquals) {
|
private Calendar setToMin(Calendar calendar, int toPart) {
|
||||||
int nextValue;
|
Part part;
|
||||||
if (isNextEquals.get()) {
|
for (int i = 0; i <= toPart; i++) {
|
||||||
// 上一层级得到相同值,下级获取下个值
|
part = Part.of(i);
|
||||||
nextValue = matcher.nextAfter(value);
|
setValue(calendar, part, getMin(part));
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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
|
//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;
|
package cn.hutool.cron.pattern;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
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.Assert;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@ -14,20 +11,27 @@ public class CronPatternNextMatchTest {
|
|||||||
@Test
|
@Test
|
||||||
public void nextMatchAfterTest(){
|
public void nextMatchAfterTest(){
|
||||||
CronPattern pattern = new CronPattern("23 12 * 12 * * *");
|
CronPattern pattern = new CronPattern("23 12 * 12 * * *");
|
||||||
|
|
||||||
|
// 时间正常递增
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
final Calendar calendar = pattern.nextMatchAfter(
|
Calendar calendar = pattern.nextMatchAfter(
|
||||||
DateUtil.parse("2022-04-12 09:12:24").toCalendar());
|
DateUtil.parse("2022-04-12 09:12:12").toCalendar());
|
||||||
|
|
||||||
Console.log(DateUtil.date(calendar));
|
|
||||||
Assert.assertTrue(pattern.match(calendar, true));
|
Assert.assertTrue(pattern.match(calendar, true));
|
||||||
}
|
Assert.assertEquals("2022-04-12 09:12:23", DateUtil.date(calendar).toString());
|
||||||
|
|
||||||
@Test
|
// 秒超出规定值的最大值,小时+1
|
||||||
@Ignore
|
//noinspection ConstantConditions
|
||||||
public void calendarTest(){
|
calendar = pattern.nextMatchAfter(
|
||||||
final Calendar ca = Calendar.getInstance();
|
DateUtil.parse("2022-04-12 09:12:24").toCalendar());
|
||||||
ca.set(Calendar.DAY_OF_WEEK, Week.SATURDAY.getValue());
|
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