Skip to content

Instantly share code, notes, and snippets.

@mStirner
Created October 31, 2019 14:32
Show Gist options
  • Save mStirner/f0dafd2c14ef17918f391fd584dfd8e6 to your computer and use it in GitHub Desktop.
Save mStirner/f0dafd2c14ef17918f391fd584dfd8e6 to your computer and use it in GitHub Desktop.
const events = require("events").EventEmitter;
/*
Added complex matches by Shimon Doodkin 2012
Developed by Elijah Rutschman 2009 - http://elijahr.blogspot.com/2009/03/javascript-cron.html
*/
/*
a typical cron entry has either wildcards (*) or an integer:
.---------------- minute (0 - 59)
| .-------------- hour (0 - 23)
| | .------------ day of month (1 - 31)
| | | .---------- month (1 - 12)
| | | | .-------- day of week (0 - 6) (Sunday=0)
| | | | |
* * * * *
*/
// m h d M w
//cron.add("* * * * *", function(){console.log('cron job that runs every minute')})
console.log("Started...");
function Cron(options) {
this.options = Object.assign({
autostart: true
}, options);
this.jobs = [];
this.interval = null;
if (this.options.autostart) {
process.nextTick(() => {
this.start();
});
}
};
Cron.prototype.add = function (str, cb) {
let job = {};
let items = str.match(/^([0-9,\-\/]+|\*{1}|\*{1}\/[0-9]+)\s+([0-9,\-\/]+|\*{1}|\*{1}\/[0-9]+)\s+([0-9,\-\/]+|\*{1}|\*{1}\/[0-9]+)\s+([0-9,\-\/]+|\*{1}|\*{1}\/[0-9]+)\s+([0-9,\-\/]+|\*{1}|\*{1}\/[0-9]+)\s*$/);
job.minute = this._parse(items[1]);
job.hour = this._parse(items[2]);
job.date = this._parse(items[3]);
job.month = this._parse(items[4]);
job.day = this._parse(items[5]);
job.cb = cb;
this.jobs.push(job);
};
Cron.prototype.stop = function () {
clearInterval(this.interval);
}
Cron.prototype.start = function () {
this.stop();
this.interval = setInterval(() => {
this._process();
}, 1000); //600000
}
Cron.prototype._match = function (a, b) {
for (var c, b0, i = 0; i < a.length; i++) {
c = a[i];
if (c[0] === -1 || (b >= c[0] && b <= c[1])) {
b0 = b - c[0]; // make the modulo start from 1st miniture of from matched time, not first minute of from 0 minutes
if (c[2] === -1 || b0 === 0 || b0 % c[2] === 0)
return true;
}
}
return false;
};
Cron.prototype._parse = function (v) {
return v.split(',').map((i) => {
let z = i.split('/');
let x = z[0].split('-');
if (x[0] == "*") {
x[0] = -1;
}
if (x.length == 1) {
x.push(x[0]);
}
x[2] = z.length === 1 ? -1 : z[1];
// parsed array structure:
x[0] = parseInt(x[0]);// 0 - from
x[1] = parseInt(x[1]);// 1 - to
x[2] = parseInt(x[2]);// 2 modulus
return x;
});
};
Cron.prototype._process = function () {
let now = new Date();
for (let i = 0; i < this.jobs.length; i++) {
if (this._match(this.jobs[i].minute, now.getMinutes())) {
if (this._match(this.jobs[i].hour, now.getHours())) {
if (this._match(this.jobs[i].date, now.getDate())) {
if (this._match(this.jobs[i].month, now.getMonth())) {
if (this._match(this.jobs[i].day, now.getDay())) {
this.jobs[i].cb();
}
}
}
}
}
}
};
const cron = new Cron();
// when cron is not running:
// queue up some jobs to run
cron.add("* * * * *", function () { console.log(Date.now(), 'cron job 0 just ran') })
cron.add("*/6 * * * *", function () { console.log(Date.now(), 'cron job 1 just ran') })
cron.add("05 * * * *", function () { console.log(Date.now(), 'cron job 2 just ran') })
cron.add("15 * * * *", function () { console.log(Date.now(), 'cron job 3 just ran') })
cron.add("30 * * * *", function () { console.log(Date.now(), 'cron job 4 just ran') })
cron.add("45 * * * *", function () { console.log(Date.now(), 'cron job 8 just ran') })
cron.add("50 * * * *", function () { console.log(Date.now(), 'cron job 9 just ran') })
cron.start();
// Cron already running, but we can add more jobs, no problem
cron.add("0 * * * *", function () { console.log(Date.now(), 'cron job 5 just ran') })
cron.add("20 9 * * 1,2,3,4,5", function () { console.log(Date.now(), 'at 9:07 of every morning from sunday to thursday') })
//testing the rulls matching:
var x;
console.log(x = cron._parse("5,10,15,20,25,30,35,40,45,50,55")) // ruls can be 1-2/3,3-4/5 many match options are seperated by comma. but no spacing in between
console.log(cron._match(x, 15));
/// each place can be : [number or number-number or *]/[modulus],[number or number-number or *]/[modulus],...
// * any number
// 5 number is 5
// 2-10 number from 5 to 10
// */3 every 3rd will run, - optionaly after the / comes modulus, modulus calulates reminder, if reminder is zero means it devides by that number exactly
// 2-10/3 between 5 to 10 every 3rd will run
//
// 2-10,12-16 many matchs but no spacing in between
// 2-10/5,12-16/2,*/10 alot matchs example
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment