mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add methods
This commit is contained in:
parent
4fbda4565a
commit
8718e6dfe1
@ -13,6 +13,7 @@
|
|||||||
* 【core 】 【可能兼容问题】Base58分离编码和解码
|
* 【core 】 【可能兼容问题】Base58分离编码和解码
|
||||||
* 【core 】 【可能兼容问题】Base62分离编码和解码,增加inverted模式支持
|
* 【core 】 【可能兼容问题】Base62分离编码和解码,增加inverted模式支持
|
||||||
* 【core 】 【兼容问题 】PunyCode参数由String改为Charsequence
|
* 【core 】 【兼容问题 】PunyCode参数由String改为Charsequence
|
||||||
|
* 【cron 】 【可能兼容问题】SimpleValueParser改名为AbsValueParser,改为abstract
|
||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
|
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
|
||||||
|
@ -1,51 +1,109 @@
|
|||||||
package cn.hutool.cron.pattern.matcher;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
import cn.hutool.cron.pattern.parser.DayOfMonthValueParser;
|
import cn.hutool.cron.pattern.matcher.AlwaysTrueValueMatcher;
|
||||||
import cn.hutool.cron.pattern.parser.ValueParser;
|
import cn.hutool.cron.pattern.matcher.BoolArrayValueMatcher;
|
||||||
import cn.hutool.cron.pattern.parser.YearValueParser;
|
import cn.hutool.cron.pattern.matcher.ValueMatcher;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ValueMatcher} 构建器,用于构建表达式中每一项的匹配器
|
* 简易值转换器。将给定String值转为int,并限定最大值和最小值<br>
|
||||||
* @author Looly
|
* 此类同时识别{@code L} 为最大值。
|
||||||
*
|
*
|
||||||
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class ValueMatcherBuilder {
|
public abstract class AbsValueParser implements ValueParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小值(包括)
|
||||||
|
*/
|
||||||
|
protected int min;
|
||||||
|
/**
|
||||||
|
* 最大值(包括)
|
||||||
|
*/
|
||||||
|
protected int max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param min 最小值(包括)
|
||||||
|
* @param max 最大值(包括)
|
||||||
|
*/
|
||||||
|
public AbsValueParser(int min, int max) {
|
||||||
|
if (min > max) {
|
||||||
|
this.min = max;
|
||||||
|
this.max = min;
|
||||||
|
} else {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parse(String value) throws CronException {
|
||||||
|
if ("L".equalsIgnoreCase(value)) {
|
||||||
|
// L表示最大值
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
try {
|
||||||
|
i = Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new CronException(e, "Invalid integer value: '{}'", value);
|
||||||
|
}
|
||||||
|
if (i < min || i > max) {
|
||||||
|
throw new CronException("Value {} out of range: [{} , {}]", i, min, max);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMin() {
|
||||||
|
return this.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMax() {
|
||||||
|
return this.max;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理定时任务表达式每个时间字段<br>
|
* 处理定时任务表达式每个时间字段<br>
|
||||||
* 多个时间使用逗号分隔
|
* 多个时间使用逗号分隔
|
||||||
*
|
*
|
||||||
* @param value 某个时间字段
|
* @param value 某个时间字段
|
||||||
* @param parser 针对这个时间字段的解析器
|
|
||||||
* @return List
|
* @return List
|
||||||
*/
|
*/
|
||||||
public static ValueMatcher build(String value, ValueParser parser) {
|
@Override
|
||||||
|
public ValueMatcher parseAsValueMatcher(String value) {
|
||||||
if (isMatchAllStr(value)) {
|
if (isMatchAllStr(value)) {
|
||||||
//兼容Quartz的"?"表达式,不会出现互斥情况,与"*"作用相同
|
//兼容Quartz的"?"表达式,不会出现互斥情况,与"*"作用相同
|
||||||
return new AlwaysTrueValueMatcher();
|
return new AlwaysTrueValueMatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Integer> values = parseArray(value, parser);
|
List<Integer> values = parseArray(value);
|
||||||
if (values.size() == 0) {
|
if (values.size() == 0) {
|
||||||
throw new CronException("Invalid field: [{}]", value);
|
throw new CronException("Invalid field: [{}]", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser instanceof DayOfMonthValueParser) {
|
return buildValueMatcher(values);
|
||||||
//考虑每月的天数不同,且存在闰年情况,日匹配单独使用
|
}
|
||||||
return new DayOfMonthValueMatcher(values);
|
|
||||||
}else if(parser instanceof YearValueParser){
|
/**
|
||||||
//考虑年数字太大,不适合boolean数组,单独使用列表遍历匹配
|
* 根据解析的数字值列表构建{@link ValueMatcher}<br>
|
||||||
return new YearValueMatcher(values);
|
* 默认为{@link BoolArrayValueMatcher},如果有特殊实现,子类须重写此方法
|
||||||
}else {
|
*
|
||||||
return new BoolArrayValueMatcher(values);
|
* @param values 数字值列表
|
||||||
}
|
* @return {@link ValueMatcher}
|
||||||
|
*/
|
||||||
|
protected ValueMatcher buildValueMatcher(List<Integer> values){
|
||||||
|
return new BoolArrayValueMatcher(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,15 +114,14 @@ public class ValueMatcherBuilder {
|
|||||||
* <li><strong>a,b,c,d</strong></li>
|
* <li><strong>a,b,c,d</strong></li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* @param value 子表达式值
|
* @param value 子表达式值
|
||||||
* @param parser 针对这个字段的解析器
|
|
||||||
* @return 值列表
|
* @return 值列表
|
||||||
*/
|
*/
|
||||||
private static List<Integer> parseArray(String value, ValueParser parser){
|
private List<Integer> parseArray(String value){
|
||||||
final List<Integer> values = new ArrayList<>();
|
final List<Integer> values = new ArrayList<>();
|
||||||
|
|
||||||
final List<String> parts = StrUtil.split(value, StrUtil.C_COMMA);
|
final List<String> parts = StrUtil.split(value, StrUtil.C_COMMA);
|
||||||
for (String part : parts) {
|
for (String part : parts) {
|
||||||
CollUtil.addAllIfNotContains(values, parseStep(part, parser));
|
CollUtil.addAllIfNotContains(values, parseStep(part));
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
@ -79,22 +136,21 @@ public class ValueMatcherBuilder {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param value 表达式值
|
* @param value 表达式值
|
||||||
* @param parser 针对这个时间字段的解析器
|
|
||||||
* @return List
|
* @return List
|
||||||
*/
|
*/
|
||||||
private static List<Integer> parseStep(String value, ValueParser parser) {
|
private List<Integer> parseStep(String value) {
|
||||||
final List<String> parts = StrUtil.split(value, StrUtil.C_SLASH);
|
final List<String> parts = StrUtil.split(value, StrUtil.C_SLASH);
|
||||||
int size = parts.size();
|
int size = parts.size();
|
||||||
|
|
||||||
List<Integer> results;
|
List<Integer> results;
|
||||||
if (size == 1) {// 普通形式
|
if (size == 1) {// 普通形式
|
||||||
results = parseRange(value, -1, parser);
|
results = parseRange(value, -1);
|
||||||
} else if (size == 2) {// 间隔形式
|
} else if (size == 2) {// 间隔形式
|
||||||
final int step = parser.parse(parts.get(1));
|
final int step = parse(parts.get(1));
|
||||||
if (step < 1) {
|
if (step < 1) {
|
||||||
throw new CronException("Non positive divisor for field: [{}]", value);
|
throw new CronException("Non positive divisor for field: [{}]", value);
|
||||||
}
|
}
|
||||||
results = parseRange(parts.get(0), step, parser);
|
results = parseRange(parts.get(0), step);
|
||||||
} else {
|
} else {
|
||||||
throw new CronException("Invalid syntax of field: [{}]", value);
|
throw new CronException("Invalid syntax of field: [{}]", value);
|
||||||
}
|
}
|
||||||
@ -113,18 +169,17 @@ public class ValueMatcherBuilder {
|
|||||||
*
|
*
|
||||||
* @param value 范围表达式
|
* @param value 范围表达式
|
||||||
* @param step 步进
|
* @param step 步进
|
||||||
* @param parser 针对这个时间字段的解析器
|
|
||||||
* @return List
|
* @return List
|
||||||
*/
|
*/
|
||||||
private static List<Integer> parseRange(String value, int step, ValueParser parser) {
|
private List<Integer> parseRange(String value, int step) {
|
||||||
final List<Integer> results = new ArrayList<>();
|
final List<Integer> results = new ArrayList<>();
|
||||||
|
|
||||||
// 全部匹配形式
|
// 全部匹配形式
|
||||||
if (value.length() <= 2) {
|
if (value.length() <= 2) {
|
||||||
//根据步进的第一个数字确定起始时间,类似于 12/3则从12(秒、分等)开始
|
//根据步进的第一个数字确定起始时间,类似于 12/3则从12(秒、分等)开始
|
||||||
int minValue = parser.getMin();
|
int minValue = getMin();
|
||||||
if(false == isMatchAllStr(value)) {
|
if(false == isMatchAllStr(value)) {
|
||||||
minValue = Math.max(minValue, parser.parse(value));
|
minValue = Math.max(minValue, parse(value));
|
||||||
}else {
|
}else {
|
||||||
//在全匹配模式下,如果步进不存在,表示步进为1
|
//在全匹配模式下,如果步进不存在,表示步进为1
|
||||||
if(step < 1) {
|
if(step < 1) {
|
||||||
@ -132,7 +187,7 @@ public class ValueMatcherBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(step > 0) {
|
if(step > 0) {
|
||||||
final int maxValue = parser.getMax();
|
final int maxValue = getMax();
|
||||||
if(minValue > maxValue) {
|
if(minValue > maxValue) {
|
||||||
throw new CronException("Invalid value {} > {}", minValue, maxValue);
|
throw new CronException("Invalid value {} > {}", minValue, maxValue);
|
||||||
}
|
}
|
||||||
@ -151,15 +206,15 @@ public class ValueMatcherBuilder {
|
|||||||
List<String> parts = StrUtil.split(value, '-');
|
List<String> parts = StrUtil.split(value, '-');
|
||||||
int size = parts.size();
|
int size = parts.size();
|
||||||
if (size == 1) {// 普通值
|
if (size == 1) {// 普通值
|
||||||
final int v1 = parser.parse(value);
|
final int v1 = parse(value);
|
||||||
if(step > 0) {//类似 20/2的形式
|
if(step > 0) {//类似 20/2的形式
|
||||||
NumberUtil.appendRange(v1, parser.getMax(), step, results);
|
NumberUtil.appendRange(v1, getMax(), step, results);
|
||||||
}else {
|
}else {
|
||||||
results.add(v1);
|
results.add(v1);
|
||||||
}
|
}
|
||||||
} else if (size == 2) {// range值
|
} else if (size == 2) {// range值
|
||||||
final int v1 = parser.parse(parts.get(0));
|
final int v1 = parse(parts.get(0));
|
||||||
final int v2 = parser.parse(parts.get(1));
|
final int v2 = parse(parts.get(1));
|
||||||
if(step < 1) {
|
if(step < 1) {
|
||||||
//在range模式下,如果步进不存在,表示步进为1
|
//在range模式下,如果步进不存在,表示步进为1
|
||||||
step = 1;
|
step = 1;
|
||||||
@ -167,10 +222,10 @@ public class ValueMatcherBuilder {
|
|||||||
if (v1 < v2) {// 正常范围,例如:2-5
|
if (v1 < v2) {// 正常范围,例如:2-5
|
||||||
NumberUtil.appendRange(v1, v2, step, results);
|
NumberUtil.appendRange(v1, v2, step, results);
|
||||||
} else if (v1 > v2) {// 逆向范围,反选模式,例如:5-2
|
} else if (v1 > v2) {// 逆向范围,反选模式,例如:5-2
|
||||||
NumberUtil.appendRange(v1, parser.getMax(), step, results);
|
NumberUtil.appendRange(v1, getMax(), step, results);
|
||||||
NumberUtil.appendRange(parser.getMin(), v2, step, results);
|
NumberUtil.appendRange(getMin(), v2, step, results);
|
||||||
} else {// v1 == v2,此时与单值模式一致
|
} else {// v1 == v2,此时与单值模式一致
|
||||||
NumberUtil.appendRange(v1, parser.getMax(), step, results);
|
NumberUtil.appendRange(v1, getMax(), step, results);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new CronException("Invalid syntax of field: [{}]", value);
|
throw new CronException("Invalid syntax of field: [{}]", value);
|
@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
import cn.hutool.cron.pattern.matcher.AlwaysTrueValueMatcher;
|
import cn.hutool.cron.pattern.matcher.AlwaysTrueValueMatcher;
|
||||||
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
import cn.hutool.cron.pattern.matcher.ValueMatcherBuilder;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -78,55 +77,40 @@ public class CronPatternParser {
|
|||||||
throw new CronException("Pattern [{}] is invalid, it must be 5-7 parts!", pattern);
|
throw new CronException("Pattern [{}] is invalid, it must be 5-7 parts!", pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 秒
|
// 秒,如果不支持秒的表达式,则第一位按照表达式生成时间的秒数赋值,表示整分匹配
|
||||||
if (1 == offset) {// 支持秒的表达式
|
final String secondPart = (1 == offset) ? parts[0] : String.valueOf(DateUtil.date().second());
|
||||||
try {
|
parseToTable(SECOND_VALUE_PARSER, secondPart);
|
||||||
matcherTable.secondMatchers.add(ValueMatcherBuilder.build(parts[0], SECOND_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'second' field error!", pattern);
|
|
||||||
}
|
|
||||||
} else {// 不支持秒的表达式,则第一位按照表达式生成时间的秒数赋值,表示整分匹配
|
|
||||||
matcherTable.secondMatchers.add(ValueMatcherBuilder.build(String.valueOf(DateUtil.date().second()), SECOND_VALUE_PARSER));
|
|
||||||
}
|
|
||||||
// 分
|
// 分
|
||||||
try {
|
parseToTable(MINUTE_VALUE_PARSER, parts[offset]);
|
||||||
matcherTable.minuteMatchers.add(ValueMatcherBuilder.build(parts[offset], MINUTE_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
// 时
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'minute' field error!", pattern);
|
parseToTable(HOUR_VALUE_PARSER, parts[1 + offset]);
|
||||||
}
|
|
||||||
// 小时
|
// 天
|
||||||
try {
|
parseToTable(DAY_OF_MONTH_VALUE_PARSER, parts[2 + offset]);
|
||||||
matcherTable.hourMatchers.add(ValueMatcherBuilder.build(parts[1 + offset], HOUR_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'hour' field error!", pattern);
|
|
||||||
}
|
|
||||||
// 每月第几天
|
|
||||||
try {
|
|
||||||
matcherTable.dayOfMonthMatchers.add(ValueMatcherBuilder.build(parts[2 + offset], DAY_OF_MONTH_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'day of month' field error!", pattern);
|
|
||||||
}
|
|
||||||
// 月
|
// 月
|
||||||
try {
|
parseToTable(MONTH_VALUE_PARSER, parts[3 + offset]);
|
||||||
matcherTable.monthMatchers.add(ValueMatcherBuilder.build(parts[3 + offset], MONTH_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
// 周
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'month' field error!", pattern);
|
parseToTable(DAY_OF_WEEK_VALUE_PARSER, parts[4 + offset]);
|
||||||
}
|
|
||||||
// 星期几
|
|
||||||
try {
|
|
||||||
matcherTable.dayOfWeekMatchers.add(ValueMatcherBuilder.build(parts[4 + offset], DAY_OF_WEEK_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'day of week' field error!", pattern);
|
|
||||||
}
|
|
||||||
// 年
|
// 年
|
||||||
if (parts.length == 7) {// 支持年的表达式
|
if (parts.length == 7) {// 支持年的表达式
|
||||||
try {
|
parseToTable(YEAR_VALUE_PARSER, parts[6]);
|
||||||
matcherTable.yearMatchers.add(ValueMatcherBuilder.build(parts[6], YEAR_VALUE_PARSER));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CronException(e, "Invalid pattern [{}], parsing 'year' field error!", pattern);
|
|
||||||
}
|
|
||||||
} else {// 不支持年的表达式,全部匹配
|
} else {// 不支持年的表达式,全部匹配
|
||||||
matcherTable.yearMatchers.add(new AlwaysTrueValueMatcher());
|
matcherTable.yearMatchers.add(new AlwaysTrueValueMatcher());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将表达式解析后加入到{@link #matcherTable}中
|
||||||
|
*
|
||||||
|
* @param valueParser 表达式解析器
|
||||||
|
* @param patternPart 表达式部分
|
||||||
|
*/
|
||||||
|
private void parseToTable(ValueParser valueParser, String patternPart) {
|
||||||
|
valueParser.parseTo(this.matcherTable, patternPart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.DayOfMonthValueMatcher;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
import cn.hutool.cron.pattern.matcher.ValueMatcher;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每月的几号值处理<br>
|
* 每月的几号值处理<br>
|
||||||
@ -9,8 +14,11 @@ import cn.hutool.cron.CronException;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DayOfMonthValueParser extends SimpleValueParser {
|
public class DayOfMonthValueParser extends AbsValueParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
public DayOfMonthValueParser() {
|
public DayOfMonthValueParser() {
|
||||||
super(1, 31);
|
super(1, 31);
|
||||||
}
|
}
|
||||||
@ -23,4 +31,19 @@ public class DayOfMonthValueParser extends SimpleValueParser {
|
|||||||
return super.parse(value);
|
return super.parse(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.dayOfMonthMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'day of month' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ValueMatcher buildValueMatcher(List<Integer> values) {
|
||||||
|
//考虑每月的天数不同,且存在闰年情况,日匹配单独使用
|
||||||
|
return new DayOfMonthValueMatcher(values);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 星期值处理<br>
|
* 星期值处理<br>
|
||||||
@ -9,7 +10,7 @@ import cn.hutool.cron.CronException;
|
|||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class DayOfWeekValueParser extends SimpleValueParser {
|
public class DayOfWeekValueParser extends AbsValueParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Weeks aliases.
|
* Weeks aliases.
|
||||||
@ -33,6 +34,15 @@ public class DayOfWeekValueParser extends SimpleValueParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.dayOfWeekMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'day of week' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析别名
|
* 解析别名
|
||||||
*
|
*
|
||||||
|
@ -1,15 +1,26 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 小时值处理<br>
|
* 小时值处理<br>
|
||||||
* 小时被限定在0-23
|
* 小时被限定在0-23
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class HourValueParser extends SimpleValueParser {
|
public class HourValueParser extends AbsValueParser {
|
||||||
|
|
||||||
public HourValueParser() {
|
public HourValueParser() {
|
||||||
super(0, 23);
|
super(0, 23);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.hourMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'hour' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,29 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分钟值处理<br>
|
* 分钟值处理<br>
|
||||||
* 限定于0-59
|
* 限定于0-59
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class MinuteValueParser extends SimpleValueParser {
|
public class MinuteValueParser extends AbsValueParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
public MinuteValueParser() {
|
public MinuteValueParser() {
|
||||||
super(0, 59);
|
super(0, 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.minuteMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'minute' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 月份值处理<br>
|
* 月份值处理<br>
|
||||||
@ -8,7 +9,7 @@ import cn.hutool.cron.CronException;
|
|||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class MonthValueParser extends SimpleValueParser {
|
public class MonthValueParser extends AbsValueParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Months aliases.
|
* Months aliases.
|
||||||
@ -28,6 +29,15 @@ public class MonthValueParser extends SimpleValueParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.monthMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'month' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析别名
|
* 解析别名
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 秒值处理<br>
|
* 秒值处理<br>
|
||||||
* 限定于0-59
|
* 限定于0-59
|
||||||
@ -7,4 +10,13 @@ package cn.hutool.cron.pattern.parser;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class SecondValueParser extends MinuteValueParser {
|
public class SecondValueParser extends MinuteValueParser {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.secondMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'second' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
|
||||||
|
|
||||||
import cn.hutool.cron.CronException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 简易值转换器。将给定String值转为int,并限定最大值和最小值<br>
|
|
||||||
* 此类同时识别{@code L} 为最大值。
|
|
||||||
*
|
|
||||||
* @author Looly
|
|
||||||
*/
|
|
||||||
public class SimpleValueParser implements ValueParser {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最小值(包括)
|
|
||||||
*/
|
|
||||||
protected int min;
|
|
||||||
/**
|
|
||||||
* 最大值(包括)
|
|
||||||
*/
|
|
||||||
protected int max;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造
|
|
||||||
*
|
|
||||||
* @param min 最小值(包括)
|
|
||||||
* @param max 最大值(包括)
|
|
||||||
*/
|
|
||||||
public SimpleValueParser(int min, int max) {
|
|
||||||
if (min > max) {
|
|
||||||
this.min = max;
|
|
||||||
this.max = min;
|
|
||||||
} else {
|
|
||||||
this.min = min;
|
|
||||||
this.max = max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int parse(String value) throws CronException {
|
|
||||||
if ("L".equalsIgnoreCase(value)) {
|
|
||||||
// L表示最大值
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i;
|
|
||||||
try {
|
|
||||||
i = Integer.parseInt(value);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new CronException(e, "Invalid integer value: '{}'", value);
|
|
||||||
}
|
|
||||||
if (i < min || i > max) {
|
|
||||||
throw new CronException("Value {} out of range: [{} , {}]", i, min, max);
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMin() {
|
|
||||||
return this.min;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMax() {
|
|
||||||
return this.max;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,8 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
import cn.hutool.cron.pattern.matcher.ValueMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 值处理接口<br>
|
* 值处理接口<br>
|
||||||
* 值处理用于限定表达式中相应位置的值范围,并转换表达式值为int值
|
* 值处理用于限定表达式中相应位置的值范围,并转换表达式值为int值
|
||||||
@ -8,6 +11,28 @@ package cn.hutool.cron.pattern.parser;
|
|||||||
*/
|
*/
|
||||||
public interface ValueParser {
|
public interface ValueParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析表达式后,加入到{@link MatcherTable}的对应列表中
|
||||||
|
*
|
||||||
|
* @param matcherTable {@link MatcherTable}
|
||||||
|
* @param pattern 对应时间部分的表达式
|
||||||
|
*/
|
||||||
|
void parseTo(MatcherTable matcherTable, String pattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析表达式对应部分为{@link ValueMatcher},支持的表达式包括:
|
||||||
|
* <ul>
|
||||||
|
* <li>单值或通配符形式,如 <strong>a</strong> 或 <strong>*</strong></li>
|
||||||
|
* <li>数组形式,如 <strong>1,2,3</strong></li>
|
||||||
|
* <li>间隔形式,如 <strong>a/b</strong> 或 <strong>*/b</strong></li>
|
||||||
|
* <li>范围形式,如 <strong>3-8</strong></li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param pattern 对应时间部分的表达式
|
||||||
|
* @return {@link ValueMatcher}
|
||||||
|
*/
|
||||||
|
ValueMatcher parseAsValueMatcher(String pattern);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理String值并转为int<br>
|
* 处理String值并转为int<br>
|
||||||
* 转换包括:
|
* 转换包括:
|
||||||
|
@ -1,15 +1,36 @@
|
|||||||
package cn.hutool.cron.pattern.parser;
|
package cn.hutool.cron.pattern.parser;
|
||||||
|
|
||||||
|
import cn.hutool.cron.CronException;
|
||||||
|
import cn.hutool.cron.pattern.matcher.MatcherTable;
|
||||||
|
import cn.hutool.cron.pattern.matcher.ValueMatcher;
|
||||||
|
import cn.hutool.cron.pattern.matcher.YearValueMatcher;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 年值处理<br>
|
* 年值处理<br>
|
||||||
* 年的限定在1970-2099年
|
* 年的限定在1970-2099年
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class YearValueParser extends SimpleValueParser {
|
public class YearValueParser extends AbsValueParser {
|
||||||
|
|
||||||
public YearValueParser() {
|
public YearValueParser() {
|
||||||
super(1970, 2099);
|
super(1970, 2099);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parseTo(MatcherTable matcherTable, String pattern) {
|
||||||
|
try {
|
||||||
|
matcherTable.yearMatchers.add(parseAsValueMatcher(pattern));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CronException(e, "Invalid pattern [{}], parsing 'year' field error!", pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ValueMatcher buildValueMatcher(List<Integer> values) {
|
||||||
|
//考虑年数字太大,不适合boolean数组,单独使用列表遍历匹配
|
||||||
|
return new YearValueMatcher(values);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user