cron表达式支持旬的改造.docx
《cron表达式支持旬的改造.docx》由会员分享,可在线阅读,更多相关《cron表达式支持旬的改造.docx(62页珍藏版)》请在冰豆网上搜索。
cron表达式支持旬的改造
packagecom.shinfotech.cmes.standard.tools;
importjava.io.Serializable;
importjava.text.ParseException;
importjava.util.Arrays;
importjava.util.Calendar;
importjava.util.Collections;
importjava.util.Date;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.LinkedList;
importjava.util.List;
importjava.util.Locale;
importjava.util.Map;
importjava.util.SortedSet;
importjava.util.StringTokenizer;
importjava.util.TimeZone;
importjava.util.TreeSet;
importorg.quartz.CronTrigger;
/**
*CronExpression官方版本不支持月份倒数第几天,仅支持月份最后一天"L",但业务需求需要知道倒数第二天。
现在加上兼容如"2L(每月倒数第二天),10L","5-2L(5号到每月倒数第二天),5-10L","5-L"(5号到每月最后一天)的表达式支持。
同时加入了对于旬的支持例如:
每旬倒数第二天10点15分钟触发"015102LX*?
"
*
*@authoryuch
*
*/
@SuppressWarnings({"rawtypes","unchecked"})
publicclassCronExpressionimplementsSerializable,Cloneable{
privatestaticfinallongserialVersionUID=12423409423L;
protectedstaticfinalintSECOND=0;
protectedstaticfinalintMINUTE=1;
protectedstaticfinalintHOUR=2;
protectedstaticfinalintDAY_OF_MONTH=3;
protectedstaticfinalintMONTH=4;
protectedstaticfinalintDAY_OF_WEEK=5;
protectedstaticfinalintYEAR=6;
protectedstaticfinalintALL_SPEC_INT=99;//'*'
protectedstaticfinalintNO_SPEC_INT=98;//'?
'
protectedstaticfinalIntegerALL_SPEC=newInteger(ALL_SPEC_INT);
protectedstaticfinalIntegerNO_SPEC=newInteger(NO_SPEC_INT);
protectedstaticfinalMapmonthMap=newHashMap(20);
protectedstaticfinalMapdayMap=newHashMap(60);
protectedstaticfinalStringBLANK="\t";
protectedstaticfinalintCronTrigger_YEAR_TO_GIVEUP_SCHEDULING_AT=2299;
static{
monthMap.put("JAN",newInteger(0));
monthMap.put("FEB",newInteger
(1));
monthMap.put("MAR",newInteger
(2));
monthMap.put("APR",newInteger(3));
monthMap.put("MAY",newInteger(4));
monthMap.put("JUN",newInteger(5));
monthMap.put("JUL",newInteger(6));
monthMap.put("AUG",newInteger(7));
monthMap.put("SEP",newInteger(8));
monthMap.put("OCT",newInteger(9));
monthMap.put("NOV",newInteger(10));
monthMap.put("DEC",newInteger(11));
dayMap.put("SUN",newInteger
(1));
dayMap.put("MON",newInteger
(2));
dayMap.put("TUE",newInteger(3));
dayMap.put("WED",newInteger(4));
dayMap.put("THU",newInteger(5));
dayMap.put("FRI",newInteger(6));
dayMap.put("SAT",newInteger(7));
}
privateStringcronExpression=null;
privateTimeZonetimeZone=null;
protectedtransientTreeSetseconds;
protectedtransientTreeSetminutes;
protectedtransientTreeSethours;
protectedtransientTreeSetdaysOfMonth;
protectedtransientTreeSetmonths;
protectedtransientTreeSetdaysOfWeek;
protectedtransientTreeSetyears;
protectedtransientMonLdaySetmonLdaySet;
protectedtransientbooleanlastdayOfWeek=false;
protectedtransientintnthdayOfWeek=0;
protectedtransientintnthdayOfXun=0;
protectedtransientbooleanlastdayOfMonth=false;
protectedtransientbooleannearestWeekday=false;
protectedtransientbooleanexpressionParsed=false;
protectedtransientbooleanisLastDayOfXun=false;
/**
*ConstructsanewCronExpression
basedonthespecified
*parameter.
*
*@paramcronExpression
*Stringrepresentationofthecronexpressionthenewobject
*shouldrepresent
*@throwsjava.text.ParseException
*ifthestringexpressioncannotbeparsedintoavalid
*CronExpression
*/
publicCronExpression(StringcronExpression)throwsParseException{
if(cronExpression==null){
thrownewIllegalArgumentException("cronExpressioncannotbenull");
}
this.cronExpression=cronExpression.toUpperCase(Locale.US);
buildExpression(this.cronExpression);
}
/**
*
*@paramstart
*@paramend
*@return
*@throwsParseException
*/
publicListgetValidTimesBy(Datestart,finalDateend)
throwsParseException{
intexprOn=SECOND;
booleanisLastDayOfMonth=false;
StringdayOfMonthExpr=null;
Stringexpr=null;
StringTokenizerexprsTok=newStringTokenizer(cronExpression,BLANK,
false);
while(exprsTok.hasMoreTokens()&&exprOn<=YEAR){
expr=exprsTok.nextToken().trim();
if(exprOn==DAY_OF_MONTH&&expr.indexOf('L')!
=-1
&&expr.length()>1){
dayOfMonthExpr=expr;
expr=expr.substring(0,expr.length()-1);
isLastDayOfMonth=true;
break;
}
exprOn++;
}
if(isLastDayOfMonth){
returngetTimesDaysOfMonth(expr,dayOfMonthExpr,start,end);
}elseif(isLastDayOfXun){
LinkedListlst=newLinkedList();
lst.addAll(getTimesByStartAndEnd(replaceExpres(11-nthdayOfXun+"",DAY_OF_MONTH),start,end));
lst.addAll(getTimesByStartAndEnd(replaceExpres(21-nthdayOfXun+"",DAY_OF_MONTH),start,end));
lst.addAll(getTimesDaysOfMonth(nthdayOfXun+"",nthdayOfXun+"L",start,end));
Collections.sort(lst);
returnlst;
}else{
returngetTimesByStartAndEnd(cronExpression,start,end);
}
/*
*intexprOn=SECOND;StringTokenizerexprsTok=new
*StringTokenizer(cronExpression,BLANK,false);intlast=0;int
*firstDay=0;StringdayOfMonthExpr=null;while
*(exprsTok.hasMoreTokens()&&exprOn<=YEAR){Stringexpr=
*exprsTok.nextToken().trim();if(exprOn==DAY_OF_MONTH&&
*expr.indexOf('L')!
=-1&&expr.length()>1){dayOfMonthExpr=
*expr;expr=expr.substring(0,expr.length()-1);
*if(expr.indexOf('-')!
=-1){String[]days=expr.split("-");
*if(days.length>2||days.length<1)thrownewParseException(
*"Dayofmonthvaluesisnotimplemented"+expr,-1);
*if(days.length==2){last=StdUtils.integerValue(days[1].substring(0,
*days[1].length()-1));}firstDay=StdUtils.integerValue(days[1]);if
*((firstDay<1||last>18)&&(firstDay!
=ALL_SPEC_INT)&&
*(firstDay!
=NO_SPEC_INT)){thrownewParseException(
*"Dayofmonthvaluesmustbebetween1and28",-1);}}elselast=
*StdUtils.integerValue(expr);}exprOn++;}if((last<1||last>31)&&
*(last!
=ALL_SPEC_INT)&&(last!
=NO_SPEC_INT)){thrownew
*ParseException("Dayofmonthvaluesmustbebetween1and31",-1);
*}
*
*dayOfMonthCronExpression=cronExpression.replaceAll(dayOfMonthExpr,
*"L");Listlist=
*getTimesByStartAndEnd(dayOfMonthCronExpression,start,end);
*LinkedListlst=newLinkedList();for(Datedate:
list)
*{if(firstDay!
=0){date=DateTimeTools.dateIncreaseByDay(date,
*-last);while(date.getDate()>=firstDay){
*date=DateTimeTools.dateIncreaseByDay(date,-1);lst.add(date);
*//firstDay++;}}elselst.add(DateTimeTools.dateIncreaseByDay(date,
*-last));
*/
/*
*LinkedListlst=newLinkedList();Datedate=start;
*while(date.getTime()*this.getNextValidTimeAfter(date);lst.add(date);}returnlst;
*/
}
protectedListgetTimesDaysOfMonth(Stringexpr,StringdayOfMonthExpr,Datestart,Dateend)throwsParseException{
intlast=0;
intfirstDay=0;
if(expr.indexOf('-')!
=-1){
String[]days=expr.split("-");
if(days.length!
=2)
thrownewParseException(
"Dayofmonthvaluesisnotimplemented"+expr,
-1);
if(!
"".equals(days[1])){
last=StdUtils.integerValue(days[1].substring(0,days[1].length()));
}
firstDay=StdUtils.integerValue(days[0]);
if((firstDay<1||last>18)&&(firstDay!
=ALL_SPEC_INT)
&&(firstDay!
=NO_SPEC_INT)){
thrownewParseException(
"Dayofmonthvaluesmustbebetween1and28",-1);
}
}else
last=StdUtils.integerValue(expr);
if((last<1||last>31)&&(last!
=ALL_SPEC_INT)
&&(last!
=NO_SPEC_INT)){
thrownewParseException(
"Dayofmonthvaluesmustbebetween1and31",-1);
}
Listlist=getTimesByStartAndEnd(replaceExpres("L",DAY_OF_MONTH),start,DateTimeTools.dateIncreaseByMonth(end,1));
LinkedListlst=newLinkedList();
intlastV=last-1;
for(Datedate:
list){
if(firstDay!
=0){
date=DateTimeTools.dateIncreaseByDay(date,-lastV);
while(date.getDate()//date=DateTimeTools.dateIncreaseByDay(date,0);
lst.add(date);
}
}else
lst.add(DateTimeTools.dateIncreaseByDay(date,-lastV));
}
returnlst;
}
protectedListgetTimesByStartAndEnd(finalStringcron,
finalDatestart,finalDateend)throwsParseException{
CronTriggertrigger=newCronTrigger();
trigger.setCronExpression(cron);
LinkedListlst=newLinkedList();
if(trigger.getNextFireTime()==null){
trigger.setStartTime(start);
trigger.setEndTime(end);
puteFirstFireTime(null);
}
do{
Dated=trigger.getNextFireTime();
if(d==null)
break;
if(d.before(start)){
trigger.triggered(null);
continue;
}
if(d.after(end))
break;
lst.add(d);
trigger.triggered(null);
}while(true);
returnlst;
}
/**
*Indicateswhetherthegivendatesatisfiesthecronexpression.Notethat
*millisecondsareignored,sotwoDatesfallingondifferentmilliseconds
*ofthesamesecondwillalwayshavethesameresulthere.
*
*@paramdate
*thedatetoevaluate
*@returnabooleanindicatingwhetherthegivendatesatisfiesthecron
*expression
*/
publicbooleanisSatisfiedBy(Datedate){
CalendartestDateCal=Calendar.getInstance(getTimeZone());
testDateCal.setTime(date);
testDateCal.set(Calendar.MILLISECOND,0);
DateoriginalDate=testDateCal.getTime();
testDateCal.add(Calendar.SECOND,-1);
DatetimeAfter=getTimeAfter(testDateCal.getTime());
return((timeAfter!
=null)&&(timeAfter.equa