cron-to-quartz
Version:
Node.js JavaScript library to convert unix or linux CRON syntax to Quartz Scheduler
222 lines (166 loc) • 5.25 kB
JavaScript
;
/**
* cron-to-quartz
* @module cron-to-quartz
*
* CRON To Quartz library enables converting Unix CRON schedule syntax to Quartz Scheduler syntax.
* Some CRON syntaxes aren't fully supported by Quartz, for example specifying both DOM and DOW.
*/
/**
* Object declaration
* C2Q - Cron 2 Quartz conversion library
*
*/
var C2Q = {};
/**
* Get a Quartz CRON notation from provided Unix CRON syntax
* getQuartz
*
* Expects to get a Unix CRON syntax format, for example: 00 11,13 * * *
*
* @param {string} unix CRON format
* @return {array} array of arrays
* for example:
* [
* ['0', '00', '11,13', '*', '*', '?', '*' ]
* ]
*
*
*/
C2Q.getQuartz = function (crontab) {
var data = [];
var quartzEntry = [];
// check for cron magic entries
quartzEntry = parseCronMagics(crontab);
if (quartzEntry) {
data.push(quartzEntry);
} else {
// if cron magic entries not found, proceed to parsing normal cron format
var crontabEntry = crontab.split(' ');
quartzEntry = parseCronSyntax(crontabEntry);
data.push(quartzEntry);
// Quartz doesn't support both DOM and DOW definitions so if we find such ocurrence we'll need to
// create 2 Quartz entries, one with DOM and one with DOW to create an OR expression
if (crontabEntry[2] !== '*' && crontabEntry[4] !== '*') {
// by default, parseCronSyntax() gives priority to parse the DOM first so we reset it now to * to
// make sure we also have a variant of the CRON expression with DOW
crontabEntry[2] = '*';
quartzEntry = parseCronSyntax(crontabEntry);
data.push(quartzEntry);
}
}
return data;
};
function advanceNumber(str) {
var quartzCompatibleStr = '';
var num;
str.split('').forEach(function (chr) {
num = parseInt(chr);
// char is an actual number
if (!isNaN(num)) {
// number is in allowed range
if (num >= 0 && num <= 7) {
quartzCompatibleStr += num + 1;
} else {
// otherwise default to 1, beginning of the week
quartzCompatibleStr = 1;
}
} else {
quartzCompatibleStr += chr;
}
});
return quartzCompatibleStr;
}
/**
* parse cron
* parseCronMagics
*
* @param {string} a string representation of a unix CRON entry
* @return {array} an array representation of a Quartz CRON entry
*
*/
function parseCronSyntax(crontabEntry) {
var quartzEntry = [];
// first we initialize the seconds to 0 by default because linux CRON entries do not include a seconds definition
quartzEntry.push('0');
// quartz scheduler can't handle an OR definition, and so it doesn't support both DOM and DOW fields to be defined
// for this reason we need to shift one of them to be the value or * and the other to be ?
var toggleQuartzCompat = false;
// if the second if passed, it will remove keeping only the 5 elements
if (crontabEntry.length === 6) {
crontabEntry.shift();
}
crontabEntry.forEach(function (item, index, array) {
// index 0 = minutes
// index 1 = hours
// these cron definitions should be compatible with quartz so we push them as is
if (index === 0 || index === 1) {
quartzEntry.push(item);
}
// index 2 = DOM = Day of Month
if (index === 2) {
if (item !== '?') {
toggleQuartzCompat = true;
}
if (item === '*') {
toggleQuartzCompat = false;
item = '?';
}
quartzEntry.push(item);
}
// index 3 = Month
if (index === 3) {
quartzEntry.push(item);
}
// index 4 = DOW = Day of Week
if (index === 4) {
// day of week needs another adjustments - it is specified as 1-7 in quartz but 0-6 in crontab
var itemAbbreviated = advanceNumber(item);
if (toggleQuartzCompat === true) {
quartzEntry.push('?');
} else {
quartzEntry.push(itemAbbreviated);
}
}
// beyond index 4 we don't care and exit the loop
if (index >= 5) {
return true;
}
});
// quartz expect a last 7th parameter for scheduling yearly recurrence so we pass * by default for all years
quartzEntry.push('*');
return quartzEntry;
}
/**
* parse cron format specified with the shorthand magic @ entries, for example: @hourly
* parseCronMagics
*
* @param {string} a string representation of a unix CRON entry
* @return {array} an array representation of a Quartz CRON entry
*
*/
function parseCronMagics(crontab) {
var quartzEntry = false;
// @hourly
if (crontab.indexOf('@hourly') === 0) {
quartzEntry = ['0', '0', '*', '*', '*', '?', '*'];
}
// @daily and @midnight
if (crontab.indexOf('@daily') === 0 || crontab.indexOf('@midnight') === 0) {
quartzEntry = ['0', '0', '0', '*', '*', '?', '*'];
}
// @weekly
if (crontab.indexOf('@weekly') === 0) {
quartzEntry = ['0', '0', '0', '?', '*', '1', '*'];
}
// @monthly
if (crontab.indexOf('@monthly') === 0) {
quartzEntry = ['0', '0', '0', '1', '*', '?', '*'];
}
// @yearly and @annually
if (crontab.indexOf('@yearly') === 0 || crontab.indexOf('@annually') === 0) {
quartzEntry = ['0', '0', '0', '1', '1', '?', '*'];
}
return quartzEntry || false;
}
module.exports = C2Q;