📄 fastcronparser.java
字号:
start ^= end;
end ^= start;
}
if (start < 0) {
start = MIN_VALUE[field];
} else if (start < MIN_VALUE[field]) {
throw new ParseException("Value " + start + " in field " + field + " is lower than the minimum allowable value for this field (min=" + MIN_VALUE[field] + ")", 0);
}
if (end < 0) {
end = MAX_VALUE[field];
} else if (end > MAX_VALUE[field]) {
throw new ParseException("Value " + end + " in field " + field + " is higher than the maximum allowable value for this field (max=" + MAX_VALUE[field] + ")", 0);
}
}
if (interval < 1) {
interval = 1;
}
int i = start - MIN_VALUE[field];
// Populate the lookup table by setting all the bits corresponding to the valid field values
for (i = start - MIN_VALUE[field]; i <= (end - MIN_VALUE[field]);
i += interval) {
lookup[field] |= (1L << i);
}
// Make sure we remember the minimum value set so far
// Keep track of the highest and lowest values that have been added to this field so far
if (lookupMin[field] > start) {
lookupMin[field] = start;
}
i += (MIN_VALUE[field] - interval);
if (lookupMax[field] < i) {
lookupMax[field] = i;
}
}
/**
* Indicates if a year is a leap year or not.
*
* @param year The year to check
*
* @return <code>true</code> if the year is a leap year, <code>false</code> otherwise.
*/
private boolean isLeapYear(int year) {
return (((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0);
}
/**
* Calculate the day of the week. Sunday = 0, Monday = 1, ... , Saturday = 6. The formula
* used is an optimized version of Zeller's Congruence.
*
* @param day The day of the month (1-31)
* @param month The month (1 - 12)
* @param year The year
* @return
*/
private int dayOfWeek(int day, int month, int year) {
day += ((month < 3) ? year-- : (year - 2));
return ((((23 * month) / 9) + day + 4 + (year / 4)) - (year / 100) + (year / 400)) % 7;
}
/**
* Retrieves the number of days in the supplied month, taking into account leap years.
* If the month value is outside the range <code>MIN_VALUE[MONTH] - MAX_VALUE[MONTH]</code>
* then the year will be adjusted accordingly and the correct number of days will still
* be returned.
*
* @param month The month of interest.
* @param year The year we are checking.
*
* @return The number of days in the month.
*/
private int numberOfDaysInMonth(int month, int year) {
while (month < 1) {
month += 12;
year--;
}
while (month > 12) {
month -= 12;
year++;
}
if (month == 2) {
return isLeapYear(year) ? 29 : 28;
} else {
return DAYS_IN_MONTH[month - 1];
}
}
/**
* Quickly retrieves the day of week value (Sun = 0, ... Sat = 6) that corresponds to the
* day name that is specified in the character array. Only the first 3 characters are taken
* into account; the rest are ignored.
*
* @param element The character array
* @param i The index to start looking at
* @return The day of week value
*/
private int getDayOfWeekVal(char ch1, char[] element, int i) throws ParseException {
if ((i + 1) >= element.length) {
throw makeParseException("Unexpected end of element encountered while parsing a day name", element, i);
}
int ch2 = element[i] | 0x20;
int ch3 = element[i + 1] | 0x20;
switch (ch1 | 0x20) {
case 's': // Sunday, Saturday
if ((ch2 == 'u') && (ch3 == 'n')) {
return 0;
}
if ((ch2 == 'a') && (ch3 == 't')) {
return 6;
}
break;
case 'm': // Monday
if ((ch2 == 'o') && (ch3 == 'n')) {
return 1;
}
break;
case 't': // Tuesday, Thursday
if ((ch2 == 'u') && (ch3 == 'e')) {
return 2;
}
if ((ch2 == 'h') && (ch3 == 'u')) {
return 4;
}
break;
case 'w': // Wednesday
if ((ch2 == 'e') && (ch3 == 'd')) {
return 3;
}
break;
case 'f': // Friday
if ((ch2 == 'r') && (ch3 == 'i')) {
return 5;
}
break;
}
throw makeParseException("Unexpected character while parsing a day name", element, i - 1);
}
/**
* Quickly retrieves the month value (Jan = 1, ..., Dec = 12) that corresponds to the month
* name that is specified in the character array. Only the first 3 characters are taken
* into account; the rest are ignored.
*
* @param element The character array
* @param i The index to start looking at
* @return The month value
*/
private int getMonthVal(char ch1, char[] element, int i) throws ParseException {
if ((i + 1) >= element.length) {
throw makeParseException("Unexpected end of element encountered while parsing a month name", element, i);
}
int ch2 = element[i] | 0x20;
int ch3 = element[i + 1] | 0x20;
switch (ch1 | 0x20) {
case 'j': // January, June, July
if ((ch2 == 'a') && (ch3 == 'n')) {
return 1;
}
if (ch2 == 'u') {
if (ch3 == 'n') {
return 6;
}
if (ch3 == 'l') {
return 7;
}
}
break;
case 'f': // February
if ((ch2 == 'e') && (ch3 == 'b')) {
return 2;
}
break;
case 'm': // March, May
if (ch2 == 'a') {
if (ch3 == 'r') {
return 3;
}
if (ch3 == 'y') {
return 5;
}
}
break;
case 'a': // April, August
if ((ch2 == 'p') && (ch3 == 'r')) {
return 4;
}
if ((ch2 == 'u') && (ch3 == 'g')) {
return 8;
}
break;
case 's': // September
if ((ch2 == 'e') && (ch3 == 'p')) {
return 9;
}
break;
case 'o': // October
if ((ch2 == 'c') && (ch3 == 't')) {
return 10;
}
break;
case 'n': // November
if ((ch2 == 'o') && (ch3 == 'v')) {
return 11;
}
break;
case 'd': // December
if ((ch2 == 'e') && (ch3 == 'c')) {
return 12;
}
break;
}
throw makeParseException("Unexpected character while parsing a month name", element, i - 1);
}
/**
* Recreates the original human-readable cron expression based on the internal
* datastructure values.
*
* @return A cron expression that corresponds to the current state of the
* internal data structure.
*/
public String getExpressionSummary() {
StringBuffer buf = new StringBuffer();
buf.append(getExpressionSetSummary(MINUTE)).append(' ');
buf.append(getExpressionSetSummary(HOUR)).append(' ');
buf.append(getExpressionSetSummary(DAY_OF_MONTH)).append(' ');
buf.append(getExpressionSetSummary(MONTH)).append(' ');
buf.append(getExpressionSetSummary(DAY_OF_WEEK));
return buf.toString();
}
/**
* <p>Converts the internal datastructure that holds a particular cron field into
* a human-readable list of values of the field's contents. For example, if the
* <code>DAY_OF_WEEK</code> field was submitted that had Sunday and Monday specified,
* the string <code>0,1</code> would be returned.</p>
*
* <p>If the field contains all possible values, <code>*</code> will be returned.
*
* @param field The field.
*
* @return A human-readable string representation of the field's contents.
*/
private String getExpressionSetSummary(int field) {
if (lookup[field] == Long.MAX_VALUE) {
return "*";
}
StringBuffer buf = new StringBuffer();
boolean first = true;
for (int i = MIN_VALUE[field]; i <= MAX_VALUE[field]; i++) {
if ((lookup[field] & (1L << (i - MIN_VALUE[field]))) != 0) {
if (!first) {
buf.append(",");
} else {
first = false;
}
buf.append(String.valueOf(i));
}
}
return buf.toString();
}
/**
* Makes a <code>ParseException</code>. The exception message is constructed by
* taking the given message parameter and appending the supplied character data
* to the end of it. for example, if <code>msg == "Invalid character
* encountered"</code> and <code>data == {'A','g','u','s','t'}</code>, the resultant
* error message would be <code>"Invalid character encountered [Agust]"</code>.
*
* @param msg The error message
* @param data The data that the message
* @param offset The offset into the data where the error was encountered.
*
* @return a newly created <code>ParseException</code> object.
*/
private ParseException makeParseException(String msg, char[] data, int offset) {
char[] buf = new char[msg.length() + data.length + 3];
int msgLen = msg.length();
System.arraycopy(msg.toCharArray(), 0, buf, 0, msgLen);
buf[msgLen] = ' ';
buf[msgLen + 1] = '[';
System.arraycopy(data, 0, buf, msgLen + 2, data.length);
buf[buf.length - 1] = ']';
return new ParseException(new String(buf), offset);
}
}
class ValueSet {
public int pos;
public int value;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -