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;/***ConstructsanewCODECronExpression/CODEbasedonthespecified*parameter.**@paramcronExpression*Stringrepresentationofthecronexpressionthenewobject*shouldrepresent*@throwsjava.text.ParseException*ifthestringexpressioncannotbeparsedintoavalid*CODECronExpression/CODE*/publicCronExpression(StringcronExpression)throwsParseException{if(cronExpression==null){thrownewIllegalArgumentException(cronExpressioncannotbenull);}this.cronExpression=cronExpression.toUpperCase(Locale.US);buildExpression(this.cronExpression);}/****@paramstart*@paramend*@return*@throwsParseException*/publicListDategetValidTimesBy(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){LinkedListDatelst=newLinkedListDate();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.length2||days.length1)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*((firstDay1||last18)&&(firstDay!=ALL_SPEC_INT)&&*(firstDay!=NO_SPEC_INT)){thrownewParseException(*Dayofmonthvaluesmustbebetween1and28,-1);}