📄 crontabexpr.java
字号:
package com.pub.timeswan;
/**
* CrontabExpr 的摘要说明
*
* 表达式:
* ${sch(minute[0-59],hour[0-23],day[1-31],month[1-12],weekday[1-7][sunday-saturday],year[1900-2200])}
*
* 参数说明:
* 参数可以有0~6个,没有认为是无所谓;参数可以是:无所谓--*|null;具体一个值--10;具体多个值--10 20;一个范围--2-12:3。
*
* 举例:
* ${sch()} 每一分钟
* ${sch(30)} 每一小时的第30分钟
* ${sch(30,0 12)} 每天0和12时的第30分钟
* ${sch(30,,,,1-5)} 每周1到5的每小时的第30分钟
*/
import java.util.Calendar;
import java.util.Date;
class CrontabExpr {
static class ValueType {
static final int Arbitrary = 0;
static final int Value = 1;
static final int List = 2;
static final int Range = 3;
}
static abstract class Value {
public int _type = ValueType.Arbitrary;
public int[] _values = null;
public abstract int Start(); //{return 0;}
public abstract int End(); //{return 0;}
public abstract Calendar SetField(Calendar cal, int v);
/**
* 将表达式中的参数字符串解析成Value
*
* @param param string
*/
public void ParseParameter(String param) {
if (param.length() > 0 && param.charAt(0) != '*') {
if (param.indexOf(' ') > 0) { // list
String[] yy = param.split(" ");
_type = ValueType.List;
int[] vals = new int[yy.length];
int val;
int count = 0;
for(String y : yy) {
val = -1;
try {
val = Integer.parseInt(y);
}
catch(Throwable ex) {continue; }
if (val >= Start() && val <= End()) {
vals[count++] = val;
}
}
if (count > 0) {
if (count == yy.length) {
_values = vals;
} else {
_values = new int[count];
for (int i = 0; i < count; i++) {
_values[i] = vals[i];
}
}
}
}
else if (param.indexOf('-') >= 0) { // range:eg.1-2;1-;1-10:2;1-20:;-
//String[] yy = param.split("-");
_type = ValueType.Range;
_values = new int[3]; // step
_values[1] = param.indexOf('-');
_values[2] = param.indexOf(':');
if (_values[2] == -1) {
_values[2] = param.length();
}
int val = -1;
try {
val = Integer.parseInt(param.substring(0, _values[1]));
} catch(Throwable ex) {}
_values[0] = (val >= Start() && val <= End()) ? val :Start();
val = -1;
try {
val = Integer.parseInt(param.substring(_values[1] + 1,
_values[2] /*- _values[1] - 1*/));
} catch(Throwable ex) {}
_values[1] = (val >= Start() && val <= End()) ? val : End();
val = -1;
try {
val = Integer.parseInt(param.substring(_values[2] + 1,
param.length() /*- _values[2] - 1*/));
} catch(Throwable ex) {}
_values[2] = Math.max(1, Math.abs(val));
} else { // value
_type = ValueType.Value;
int val = -1;
boolean parseOK = true;
try {
val = Integer.parseInt(param);
} catch(Throwable ex) {parseOK = false; }
if (parseOK && val >= Start() && val <= End()) {
_values = new int[1];
_values[0] = val;
}
}
}
}
}
static class MinuteField extends Value {
public int Start() {
return 0;
}
public int End() {
return 59;
}
public Calendar SetField(Calendar cal, int v) {
// Calendar tmp = cal.getInstance();
// tmp.setTimeInMillis(cal.getTimeInMillis());
Calendar tmp = (Calendar)cal.clone();
tmp.set(Calendar.MINUTE, v);
return tmp;
}
}
static class HourField extends Value {
public int Start() {
return 0;
}
public int End() {
return 23;
}
public Calendar SetField(Calendar cal, int v) {
// Calendar tmp = cal.getInstance();
// tmp.setTimeInMillis(cal.getTimeInMillis());
// System.out.println( new Date( cal.getTimeInMillis() ));
Calendar tmp = (Calendar)cal.clone();
tmp.set(Calendar.HOUR_OF_DAY, v);
// System.out.println( new Date( tmp.getTimeInMillis() ));
return tmp;
}
}
static class DayField extends Value {
public int Start() {
return 0;
}
public int End() {
return 31;
}
public Calendar SetField(Calendar cal, int v) {
// Calendar x = t.AddMonths(1);
// x = x.AddDays( -x.Day);
// v = v > x.Day ? x.Day : v;
//
// return t.AddDays(v - t.Day);
// Calendar tmp = cal.getInstance();
// tmp.setTimeInMillis(cal.getTimeInMillis());
Calendar tmp = (Calendar)cal.clone();
tmp.set(Calendar.DATE, v);
return tmp;
}
}
static class WeekdayField extends Value {
public int Start() {
return 0;
}
public int End() {
return 6;
}
public Calendar SetField(Calendar cal, int v) {
// Calendar tmp = cal.getInstance();
// tmp.setTimeInMillis(cal.getTimeInMillis());
Calendar tmp = (Calendar)cal.clone();
// System.out.println( new Date( tmp.getTimeInMillis() ));
tmp.set(Calendar.DAY_OF_WEEK, v);
// System.out.println( new Date( tmp.getTimeInMillis() ));
return tmp;
// return t.AddDays(v - (int) t.DayOfWeek);
}
}
static class MonthField extends Value {
public int Start() {
return 1;
}
public int End() {
return 12;
}
public Calendar SetField(Calendar cal, int v) {
// return t.AddMonths(v - t.Month);
// Calendar tmp = cal.getInstance();
// tmp.setTimeInMillis(cal.getTimeInMillis());
Calendar tmp = (Calendar)cal.clone();
tmp.set(Calendar.MONTH, v);
return tmp;
}
}
static class YearField extends Value {
public int Start() {
return 1900;
}
public int End() {
return 2200;
}
public Calendar SetField(Calendar cal, int v) {
// return t.AddYears(v - t.Year);
// Calendar tmp = cal.getInstance();
// tmp.setTimeInMillis(cal.getTimeInMillis());
Calendar tmp = (Calendar)cal.clone();
tmp.set(Calendar.YEAR, v);
return tmp;
}
}
/**
* 解析表达式为 Calendar
*
* @param expr string
* 表达式字符串
*
* @return Calendar
* 解析的结果 Calendar
*/
static String exprBegin = "${sch(";
static public Calendar Parse(String expr) {
Calendar now = Calendar.getInstance();
expr = expr.toLowerCase();
int start = expr.indexOf(exprBegin);
// no express,return year 0000
if (start < 0) {
now.setTimeInMillis(0);
return now;
}
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
start += exprBegin.length();
int end = expr.indexOf(")}", start);
// no any parameter,return current_minute
if (start == end) {
return now;
}
String[] parms = expr.substring(start,end).split(",", 6);
Value[] values = new Value[parms.length];
if (parms.length >= 1 && parms[0] != null &&
parms[0].trim().length() > 0) {
values[0] = new MinuteField();
values[0].ParseParameter(parms[0].trim());
}
if (parms.length >= 2 && parms[1] != null &&
parms[1].trim().length() > 0) {
values[1] = new HourField();
values[1].ParseParameter(parms[1].trim());
}
if (parms.length >= 3 && parms[2] != null &&
parms[2].trim().length() > 0) {
values[2] = new DayField();
values[2].ParseParameter(parms[2].trim());
}
if (parms.length >= 4 && parms[3] != null &&
parms[3].trim().length() > 0) {
values[3] = new MonthField();
values[3].ParseParameter(parms[3].trim());
}
if ( /*values[2] == null && */parms.length >= 5 && parms[4] != null &&
parms[4].trim().length() > 0) { // week and day conflict,so day exclude week
values[4] = new WeekdayField();
values[4].ParseParameter(parms[4].trim());
}
if (parms.length >= 6 && parms[5] != null &&
parms[5].trim().length() > 0) {
values[5] = new YearField();
values[5].ParseParameter(parms[5].trim());
}
// combine to find lastest time
return LastestTime(now, now, values, 0);
}
/**
* 递归计算,寻找与当前时刻最接近的时刻
* @param now Calendar
* 当前时刻
* @param ct Calendar
* 计算的起点时刻
* @param vals Value[]
* Value数组
* @param start int
* 本次处理的Value在数组中的索引
* @return Calendar
* 本次计算后与now最接近的时刻
*/
static private Calendar LastestTime(Calendar now, Calendar ct, Value[] vals,int start) {
if (start >= vals.length) {return ct;}
Calendar ret = (Calendar)ct.clone();
Value val = vals[start];
//不是任意
if (val != null && val._values != null && val._type != ValueType.Arbitrary) {
Calendar tmp;
double space, MaxMinuteSpace = Double.MAX_VALUE;
if (val._type == ValueType.Value) {
return LastestTime(now, val.SetField(ct, val._values[0]), vals,start + 1);
} else if (val._type == ValueType.List) {
for (int cur : val._values) {
tmp = LastestTime(now, val.SetField(ct, cur), vals,start + 1);
space = Math.abs(now.getTimeInMillis() - tmp.getTimeInMillis());
if (space < MaxMinuteSpace) {
MaxMinuteSpace = space;
ret = tmp;
}
}
} else if (vals[start]._type == ValueType.Range) {
for (int cur = val._values[0]; cur <= val._values[1];
cur += val._values[2]) {
tmp = LastestTime(now, val.SetField(ct, cur), vals,
start + 1);
space = Math.abs(now.getTimeInMillis() - tmp.getTimeInMillis());
if (space < MaxMinuteSpace) {
MaxMinuteSpace = space;
ret = tmp;
} else {
break;
}
}
}
}
if ((start + 1) < vals.length) {
return LastestTime(now, ret, vals, start + 1);
}
return ret;
}
public static void main(String[] args) {
// System.out.println(new Date( CrontabExpr.Parse("${sch()}").getTimeInMillis() ));
// System.out.println(new Date( CrontabExpr.Parse("${sch(30)}").getTimeInMillis() ));
System.out.println(new Date( CrontabExpr.Parse("${sch(30,18-23:3)}").getTimeInMillis() ));
// System.out.println(new Date( CrontabExpr.Parse("${sch(30,,,,5-6)}").getTimeInMillis() ));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -