Comparing version 4.0.53 to 4.0.54
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Cron=e():t.Cron=e()}(this,(function(){return(()=>{"use strict";var t={d:(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{default:()=>i});function r(t,e){if(this.timezone=e,t&&t instanceof Date)this.fromDate(t);else if(void 0===t)this.fromDate(new Date);else if(t&&"string"==typeof t)this.fromString(t);else{if(!(t instanceof r))throw new TypeError("CronDate: Invalid type ("+typeof t+") passed as parameter to CronDate constructor");this.fromCronDate(t)}}function o(t){this.pattern=t,this.seconds=Array(60).fill(0),this.minutes=Array(60).fill(0),this.hours=Array(24).fill(0),this.days=Array(31).fill(0),this.months=Array(12).fill(0),this.daysOfWeek=Array(8).fill(0),this.parse()}r.prototype.fromDate=function(t){let e=t.getTime();this.timezone&&(t=function(t,e){return new Date(t.toLocaleString("en-US",{timeZone:e}))}(t,this.timezone));let r=t.getTime();this.UTCmsOffset=r-e,this.milliseconds=t.getMilliseconds(),this.seconds=t.getSeconds(),this.minutes=t.getMinutes(),this.hours=t.getHours(),this.days=t.getDate(),this.months=t.getMonth(),this.years=t.getFullYear()},r.prototype.fromCronDate=function(t){this.UTCmsOffset=t.UTCmsOffset,this.timezone=t.timezone;let e=new Date(t.years,t.months,t.days,t.hours,t.minutes,t.seconds,t.milliseconds);this.milliseconds=e.getMilliseconds(),this.seconds=e.getSeconds(),this.minutes=e.getMinutes(),this.hours=e.getHours(),this.days=e.getDate(),this.months=e.getMonth(),this.years=e.getFullYear()},r.prototype.fromString=function(t){let e=Date.parse(t);if(isNaN(e))throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");this.fromDate(new Date(e))},r.prototype.increment=function(t,e){e||(this.seconds+=1);let o=this.getTime();this.milliseconds=0;let n=this,s=function(t,e,r,o){for(let s=void 0===o?n[t]+r:0+r;s<e[t].length;s++)if(e[t][s])return n[t]=s-r,!0;return!1},i=function(){for(;h>=0;)s(a[h][0],t,a[h][2],0),h--},a=[["seconds","minutes",0],["minutes","hours",0],["hours","days",0],["days","months",-1],["months","years",0]],h=0;for(;h<5;)s(a[h][0],t,a[h][2])||(this[a[h][1]]++,i()),h++;for(;!t.daysOfWeek[this.getDate().getDay()];)this.days+=1,h=2,i();return o!=n.getTime()?(n=new r(n),this.years>=4e3?null:n.increment(t,!0)):this},r.prototype.getDate=function(){return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-this.UTCmsOffset)},r.prototype.getTime=function(){return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-this.UTCmsOffset).getTime()},o.prototype.parse=function(){if("string"!=typeof this.pattern&&this.pattern.constructor!==String)throw new TypeError("CronPattern: Pattern has to be of type string.");let t,e,r=this.pattern.trim().replace(/\s+/g," ").split(" "),o=/[^/*0-9,-]+/;if(r.length<5||r.length>6)throw new TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exacly five or six space separated parts required.");for(5===r.length&&r.unshift("0"),e=0;e<r.length;e++)if(t=r[e].trim(),o.test(t))throw new TypeError("CronPattern: configuration entry "+(e+1)+" ("+t+") contains illegal characters.");this.partToArray("seconds",r[0],0),this.partToArray("minutes",r[1],0),this.partToArray("hours",r[2],0),this.partToArray("days",r[3],-1),this.partToArray("months",r[4],-1),this.partToArray("daysOfWeek",r[5],0),this.daysOfWeek[7]&&(this.daysOfWeek[0]=1)},o.prototype.partToArray=function(t,e,r){let o,n,s,i,a,h=this[t];if("*"!==e)if(n=e.split(","),n.length>1)for(o=0;o<n.length;o++)this.partToArray(t,n[o],r);else if(-1!==e.indexOf("-")){if(n=e.split("-"),2!==n.length)throw new TypeError("CronPattern: Syntax error, illegal range: '"+e+"'");if(s=parseInt(n[0],10)+r,i=parseInt(n[1],10)+r,isNaN(s))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(i))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(s<0||i>=h.length)throw new TypeError("CronPattern: Value out of range: '"+e+"'");if(s>i)throw new TypeError("CronPattern: From value is larger than to value: '"+e+"'");for(o=s;o<=i;o++)h[o+r]=1}else if(-1!==e.indexOf("/")){if(n=e.split("/"),2!==n.length)throw new TypeError("CronPattern: Syntax error, illegal stepping: '"+e+"'");if("*"!==n[0])throw new TypeError("CronPattern: Syntax error, left part of / needs to be * : '"+e+"'");if(a=parseInt(n[1],10),isNaN(a))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(0===a)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(a>h.length)throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+h.length+")");for(o=0;o<h.length;o+=a)h[o+r]=1}else{if(o=parseInt(e,10)+r,o<0||o>=h.length)throw new TypeError("CronPattern: "+t+" value out of range: '"+e+"'");h[o]=1}else for(o=0;o<h.length;o++)h[o]=1};const n=Math.pow(2,31)-1;function s(t,e,r){return this instanceof s?(this.pattern=new o(t),"function"==typeof e&&(r=e,e=void 0),this.options=this.processOptions(e),void 0!==r&&this.schedule(r),this):new s(t,e,r)}s.prototype.processOptions=function(t){return void 0===t&&(t={}),t.paused=void 0!==t.paused&&t.paused,t.maxRuns=void 0===t.maxRuns?1/0:t.maxRuns,t.kill=!1,t.startAt&&(t.startAt=new r(t.startAt,t.timezone)),t.stopAt&&(t.stopAt=new r(t.stopAt,t.timezone)),t},s.prototype.next=function(t){let e=this._next(t);return e?e.getDate():null},s.prototype.previous=function(){return this.previousrun?this.previousrun.getDate():null},s.prototype._next=function(t){t=new r(t,this.options.timezone),this.options.startAt&&t&&t.getTime()<this.options.startAt.getTime()&&(t=new r(this.options.startAt,this.options.timezone));let e=new r(t,this.options.timezone).increment(this.pattern);return null===e||this.options.maxRuns<=0||this.options.kill||this.options.stopAt&&e.getTime()>=this.options.stopAt.getTime()?null:e},s.prototype.msToNext=function(t){t=t||new r(void 0,this.options.timezone);let e=this._next(t);return e?e.getTime()-t.getTime():null},s.prototype.stop=function(){this.options.kill=!0,this.currentTimeout&&clearTimeout(this.currentTimeout)},s.prototype.pause=function(){return(this.options.paused=!0)&&!this.options.kill},s.prototype.resume=function(){return!(this.options.paused=!1)&&!this.options.kill},s.prototype.schedule=function(t){let e=this,o=this.msToNext(e.previousrun),s=e.maxDelay||n;return o>s&&(o=s),null!==o&&(e.currentTimeout=setTimeout((function(){o!==s&&(e.options.paused||(e.options.maxRuns--,t()),e.previousrun=new r(void 0,e.options.timezone)),e.schedule(t)}),o)),this};const i=s;return e.default})()})); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Cron=e():t.Cron=e()}(this,(function(){return(()=>{"use strict";var t={d:(e,r)=>{for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{default:()=>s});function r(t,e){if(this.timezone=e,t&&t instanceof Date)this.fromDate(t);else if(void 0===t)this.fromDate(new Date);else if(t&&"string"==typeof t)this.fromString(t);else{if(!(t instanceof r))throw new TypeError("CronDate: Invalid type ("+typeof t+") passed as parameter to CronDate constructor");this.fromCronDate(t)}}function n(t){this.pattern=t,this.seconds=Array(60).fill(0),this.minutes=Array(60).fill(0),this.hours=Array(24).fill(0),this.days=Array(31).fill(0),this.months=Array(12).fill(0),this.daysOfWeek=Array(8).fill(0),this.parse()}r.prototype.fromDate=function(t){let e=t.getTime();this.timezone&&(t=function(t,e){return new Date(t.toLocaleString("en-US",{timeZone:e}))}(t,this.timezone));let r=t.getTime();this.UTCmsOffset=r-e,this.milliseconds=t.getMilliseconds(),this.seconds=t.getSeconds(),this.minutes=t.getMinutes(),this.hours=t.getHours(),this.days=t.getDate(),this.months=t.getMonth(),this.years=t.getFullYear()},r.prototype.fromCronDate=function(t){this.UTCmsOffset=t.UTCmsOffset,this.timezone=t.timezone;let e=new Date(t.years,t.months,t.days,t.hours,t.minutes,t.seconds,t.milliseconds);this.milliseconds=e.getMilliseconds(),this.seconds=e.getSeconds(),this.minutes=e.getMinutes(),this.hours=e.getHours(),this.days=e.getDate(),this.months=e.getMonth(),this.years=e.getFullYear()},r.prototype.fromString=function(t){let e=Date.parse(t);if(isNaN(e))throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");this.fromDate(new Date(e))},r.prototype.increment=function(t,e){e||(this.seconds+=1);let n=this.getTime();this.milliseconds=0;let o=this,i=function(t,e,r,n){for(let i=void 0===n?o[t]+r:0+r;i<e[t].length;i++)if(e[t][i])return o[t]=i-r,!0;return!1},s=function(){for(;p>=0;)i(a[p][0],t,a[p][2],0),p--},a=[["seconds","minutes",0],["minutes","hours",0],["hours","days",0],["days","months",-1],["months","years",0]],p=0;for(;p<5;)i(a[p][0],t,a[p][2])||(this[a[p][1]]++,s()),p++;for(;!t.daysOfWeek[this.getDate().getDay()];)this.days+=1,p=2,s();return n!=o.getTime()?(o=new r(o),this.years>=4e3?null:o.increment(t,!0)):this},r.prototype.getDate=function(){return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-this.UTCmsOffset)},r.prototype.getTime=function(){return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-this.UTCmsOffset).getTime()},n.prototype.parse=function(){if("string"!=typeof this.pattern&&this.pattern.constructor!==String)throw new TypeError("CronPattern: Pattern has to be of type string.");let t=this.pattern.trim().replace(/\s+/g," ").split(" ");if(t.length<5||t.length>6)throw new TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exacly five or six space separated parts required.");5===t.length&&t.unshift("0"),t[4]=this.replaceAlphaMonths(t[4]),t[5]=this.replaceAlphaDays(t[5]),this.throwAtIllegalCharacters(t),this.partToArray("seconds",t[0],0),this.partToArray("minutes",t[1],0),this.partToArray("hours",t[2],0),this.partToArray("days",t[3],-1),this.partToArray("months",t[4],-1),this.partToArray("daysOfWeek",t[5],0),this.daysOfWeek[7]&&(this.daysOfWeek[0]=1)},n.prototype.partToArray=function(t,e,r){let n,o,i=this[t];if("*"!==e)if(o=e.split(","),o.length>1)for(n=0;n<o.length;n++)this.partToArray(t,o[n],r);else-1!==e.indexOf("-")?this.handleRange(e,t,r):-1!==e.indexOf("/")?this.handleStepping(e,t,r):this.handleNumber(e,t,r);else for(n=0;n<i.length;n++)i[n]=1},n.prototype.throwAtIllegalCharacters=function(t){let e=/[^/*0-9,-]+/;for(let r=0;r<t.length;r++)if(e.test(t[r]))throw new TypeError("CronPattern: configuration entry "+r+" ("+t[r]+") contains illegal characters.")},n.prototype.handleNumber=function(t,e,r){let n=parseInt(t,10)+r;if(n<0||n>=this[e].length)throw new TypeError("CronPattern: "+e+" value out of range: '"+t+"'");this[e][n]=1},n.prototype.handleRange=function(t,e,r){let n=t.split("-");if(2!==n.length)throw new TypeError("CronPattern: Syntax error, illegal range: '"+t+"'");let o=parseInt(n[0],10)+r,i=parseInt(n[1],10)+r;if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(i))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(o<0||i>=this[e].length)throw new TypeError("CronPattern: Value out of range: '"+t+"'");if(o>i)throw new TypeError("CronPattern: From value is larger than to value: '"+t+"'");for(let t=o;t<=i;t++)this[e][t+r]=1},n.prototype.handleStepping=function(t,e,r){let n=t.split("/");if(2!==n.length)throw new TypeError("CronPattern: Syntax error, illegal stepping: '"+t+"'");if("*"!==n[0])throw new TypeError("CronPattern: Syntax error, left part of / needs to be * : '"+t+"'");let o=parseInt(n[1],10);if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(0===o)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(o>this[e].length)throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[e].length+")");for(let t=0;t<this[e].length;t+=o)this[e][t+r]=1},n.prototype.replaceAlphaDays=function(t){return t.replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")},n.prototype.replaceAlphaMonths=function(t){return t.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")};const o=Math.pow(2,31)-1;function i(t,e,r){return this instanceof i?(this.pattern=new n(t),"function"==typeof e&&(r=e,e=void 0),this.options=this.processOptions(e),void 0!==r&&this.schedule(r),this):new i(t,e,r)}i.prototype.processOptions=function(t){return void 0===t&&(t={}),t.paused=void 0!==t.paused&&t.paused,t.maxRuns=void 0===t.maxRuns?1/0:t.maxRuns,t.kill=!1,t.startAt&&(t.startAt=new r(t.startAt,t.timezone)),t.stopAt&&(t.stopAt=new r(t.stopAt,t.timezone)),t},i.prototype.next=function(t){let e=this._next(t);return e?e.getDate():null},i.prototype.previous=function(){return this.previousrun?this.previousrun.getDate():null},i.prototype._next=function(t){t=new r(t,this.options.timezone),this.options.startAt&&t&&t.getTime()<this.options.startAt.getTime()&&(t=new r(this.options.startAt,this.options.timezone));let e=new r(t,this.options.timezone).increment(this.pattern);return null===e||this.options.maxRuns<=0||this.options.kill||this.options.stopAt&&e.getTime()>=this.options.stopAt.getTime()?null:e},i.prototype.msToNext=function(t){t=t||new r(void 0,this.options.timezone);let e=this._next(t);return e?e.getTime()-t.getTime():null},i.prototype.stop=function(){this.options.kill=!0,this.currentTimeout&&clearTimeout(this.currentTimeout)},i.prototype.pause=function(){return(this.options.paused=!0)&&!this.options.kill},i.prototype.resume=function(){return!(this.options.paused=!1)&&!this.options.kill},i.prototype.schedule=function(t){let e=this,n=this.msToNext(e.previousrun),i=e.maxDelay||o;return n>i&&(n=i),null!==n&&(e.currentTimeout=setTimeout((function(){n!==i&&(e.options.paused||(e.options.maxRuns--,t()),e.previousrun=new r(void 0,e.options.timezone)),e.schedule(t)}),n)),this};const s=i;return e.default})()})); |
{ | ||
"name": "croner", | ||
"version": "4.0.53", | ||
"version": "4.0.54", | ||
"description": "Trigger functions in javascript using Cron syntax. No deps. All features.", | ||
@@ -5,0 +5,0 @@ "author": "Hexagon <github.com/hexagon>", |
157
README.md
@@ -7,7 +7,7 @@ # Croner | ||
* Trigger functions in javascript using [Cron](https://en.wikipedia.org/wiki/Cron#CRON_expression) syntax. | ||
* Pause, resume or stop exection efter a task is scheduled. | ||
* Pause, resume or stop execution efter a task is scheduled. | ||
* Find first date of next month, find date of next tuesday, etc. | ||
* Supports Node.js from 4.0 to current. Both require (commonjs) and import (module). | ||
* Supports browser use ([UMD](https://github.com/umdjs/umd) (standalone, requirejs etc.), [ES-module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)) | ||
* *Experimental:* Schedule in other timezone than default. | ||
* **Experimental:** Schedule in other timezones than default. | ||
@@ -27,3 +27,10 @@ Documented with [JSDoc](https://jsdoc.app/) for intellisense, and include [TypeScript](https://www.typescriptlang.org/) typings. | ||
// What date is next sunday? | ||
console.log(Cron('0 0 0 * * 7').next().toLocaleDateString()); | ||
let nextSunday = Cron('0 0 0 * * 7').next(); | ||
console.log(nextSunday.toLocaleDateString()); | ||
// How many days left to christmas eve? | ||
let msLeft = Cron('23 59 59 24 DEC *').next() - new Date(); | ||
console.log(Math.floor(msLeft/1000/3600/24) + " days left to next christmas eve"); | ||
``` | ||
@@ -33,8 +40,2 @@ | ||
### Manual | ||
* Download latest [zipball](http://github.com/Hexagon/croner/zipball/master/) | ||
* Unpack | ||
* Grab ```croner.min.js``` ([UMD](https://github.com/umdjs/umd)) or ```croner.min.mjs``` ([ES-module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)) from the [dist/](/dist) folder | ||
### Node.js | ||
@@ -55,4 +56,12 @@ | ||
### CDN | ||
### Browser | ||
#### Manual | ||
* Download latest [zipball](http://github.com/Hexagon/croner/zipball/master/) | ||
* Unpack | ||
* Grab ```croner.min.js``` ([UMD](https://github.com/umdjs/umd)) or ```croner.min.mjs``` ([ES-module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)) from the [dist/](/dist) folder | ||
#### CDN | ||
To use as a [UMD](https://github.com/umdjs/umd)-module (stand alone, [RequireJS](https://requirejs.org/) etc.) | ||
@@ -92,3 +101,3 @@ | ||
### Minimalist scheduling | ||
### Minimal | ||
```javascript | ||
@@ -105,86 +114,49 @@ // Run a function each second | ||
let nextMonth = Cron('0 0 0 1 * *').next(), | ||
nextSunday = Cron('0 0 0 * * 7').next(); | ||
nextSunday = Cron('0 0 0 * * 7').next(), | ||
nextSaturday29feb = Cron("0 0 0 29 2 6").next(); | ||
console.log("First day of next month: " + nextMonth.toLocaleDateString()); | ||
console.log("Next sunday: " + nextSunday.toLocaleDateString()); | ||
console.log("Next saturday at 29th of february: " + nextSaturday29feb.toLocaleDateString()); // 2048-02-29 | ||
``` | ||
### Minimalist scheduling with stepping and custom timezone | ||
### Expressions | ||
```javascript | ||
// Run a function every fifth second | ||
Cron('*/5 * * * * *', { timezone: 'Europe/Stockholm' }, function () { | ||
console.log('This will run every fifth second'); | ||
}); | ||
``` | ||
### Minimalist scheduling with range | ||
```javascript | ||
// Run a function the first five seconds of a minute | ||
Cron('0-4 * * * * *', function () { | ||
console.log('This will run the first five seconds every minute'); | ||
Cron('0-4 */5 1,2,3 * JAN-MAR SAT', function () { | ||
console.log('This will run the first five seconds every fifth minute of hour 1,2 and 3 every saturday in January to March'); | ||
}); | ||
``` | ||
### Minimalist scheduling with options | ||
### Options and separate scheduling | ||
```javascript | ||
// Run a function each second, limit to five runs | ||
Cron('* * * * * *', { maxRuns: 5 }, function () { | ||
console.log('This will run each second, but only five times.'); | ||
}); | ||
``` | ||
### Minimalist scheduling with job controls | ||
```javascript | ||
// Run a function each second, get reference to job | ||
var job = Cron('* * * * * *', function () { | ||
console.log('This will run each second.'); | ||
}); | ||
// Pause job | ||
job.pause(); | ||
// Resume job | ||
job.resume(); | ||
// Stop job | ||
job.stop(); | ||
// Run every minute, if you pass 5 sections to croner, seconds will default to 0 | ||
// * * * * * is equivalent to 0 * * * * * | ||
var job = Cron( | ||
'* * * * *', | ||
{ | ||
maxRuns: 5, | ||
startAt: "2021-11-01 00:00:00", | ||
stopAt: "2021-12-01 00:00:00", | ||
timezone: "Europe/Stockholm" | ||
}, | ||
function() { | ||
console.log('This will run every minute.'); | ||
} | ||
); | ||
``` | ||
### Basic scheduling | ||
### Job controls | ||
```javascript | ||
// Run every minute | ||
var scheduler = Cron('0 * * * * *'); | ||
scheduler.schedule(function() { | ||
console.log('This will run every minute'); | ||
}); | ||
``` | ||
### Scheduling with options | ||
```javascript | ||
// Run every minute | ||
var scheduler = Cron('0 * * * * *', { maxRuns: 5 }); | ||
// Schedule with options (all options are optional) | ||
scheduler.schedule(function() { | ||
console.log('This will run every minute.'); | ||
}); | ||
``` | ||
### Scheduling with controls | ||
```javascript | ||
let scheduler = Cron('* * * * * *') | ||
scheduler.schedule(function () { | ||
let job = Cron('* * * * * *', () => { | ||
console.log('This will run every second. Pause on second 10. Resume on second 15. And quit on second 20.'); | ||
console.log('Current second: ', new Date().getSeconds()); | ||
console.log('Previous run: ' + scheduler.previous()); | ||
console.log('Next run: ' + scheduler.next()); | ||
console.log('Previous run: ' + job.previous()); | ||
console.log('Next run: ' + job.next()); | ||
}); | ||
Cron('10 * * * * *', {maxRuns: 1}, () => scheduler.pause()); | ||
Cron('15 * * * * *', {maxRuns: 1}, () => scheduler.resume()); | ||
Cron('20 * * * * *', {maxRuns: 1}, () => scheduler.stop()); | ||
Cron('10 * * * * *', {maxRuns: 1}, () => job.pause()); | ||
Cron('15 * * * * *', {maxRuns: 1}, () => job.resume()); | ||
Cron('20 * * * * *', {maxRuns: 1}, () => job.stop()); | ||
``` | ||
@@ -195,11 +167,11 @@ | ||
var scheduler = Cron( <string pattern> [, { startAt: <date|string>, stopAt: <date|string>, maxRuns: <integer>, timezone: <string> } ] [, <function job> ] ) | ||
var job = Cron( <string pattern> [, { startAt: <date|string>, stopAt: <date|string>, maxRuns: <integer>, timezone: <string> } ] [, <function job> ] ); | ||
scheduler.next( [ <date previous> ] ); | ||
scheduler.msToNext( [ <date previous> ] ); | ||
scheduler.previous(); | ||
scheduler.schedule( <fn job> ); | ||
scheduler.pause(); | ||
scheduler.resume(); | ||
scheduler.stop(); | ||
job.next( [ <date previous> ] ); | ||
job.msToNext( [ <date previous> ] ); | ||
job.previous(); | ||
job.schedule( <fn job> ); | ||
job.pause(); | ||
job.resume(); | ||
job.stop(); | ||
@@ -215,4 +187,4 @@ ``` | ||
│ │ │ ┌────────── day of month (1 - 31) | ||
│ │ │ │ ┌──────── month (1 - 12) | ||
│ │ │ │ │ ┌────── day of week (0 - 6) | ||
│ │ │ │ ┌──────── month (1 - 12, JAN-DEC) | ||
│ │ │ │ │ ┌────── day of week (0 - 6, SUN-Mon) | ||
│ │ │ │ │ │ (0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0) | ||
@@ -223,4 +195,17 @@ │ │ │ │ │ │ | ||
### Details | ||
| Field | Required | Allowed values | Allowed special characters | Remarks | | ||
|--------------|----------|----------------|----------------------------|---------------------------------------| | ||
| Seconds | Optional | 0-59 | * , - / | | | ||
| Minutes | Yes | 0-59 | * , - / | | | ||
| Hours | Yes | 0-23 | * , - / | | | ||
| Day of Month | Yes | 1-31 | * , - / | | | ||
| Month | Yes | 1-12 or JAN-DEC| * , - / | | | ||
| Day of Week | Yes | 0-7 or SUN-MON| * , - / | 0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0 | | ||
**Note**: Weekday and month names are case insensitive. Both MON and mon works. | ||
## License | ||
MIT |
@@ -161,2 +161,3 @@ /* ------------------------------------------------------------------------------------ | ||
* Return previous run time | ||
* @public | ||
* | ||
@@ -287,3 +288,3 @@ * @returns {Date | null} - Previous run time | ||
// Recurseg | ||
// Recurse | ||
self.schedule(func); | ||
@@ -290,0 +291,0 @@ |
@@ -28,2 +28,3 @@ /** | ||
* Parse current pattern, will raise an error on failure | ||
* @private | ||
*/ | ||
@@ -38,6 +39,3 @@ CronPattern.prototype.parse = function () { | ||
// Split configuration on whitespace | ||
let parts = this.pattern.trim().replace(/\s+/g, " ").split(" "), | ||
part, | ||
i, | ||
reValidCron = /[^/*0-9,-]+/; | ||
let parts = this.pattern.trim().replace(/\s+/g, " ").split(" "); | ||
@@ -54,11 +52,9 @@ // Validite number of configuration entries | ||
// Validate field content | ||
for( i = 0; i < parts.length; i++ ) { | ||
part = parts[i].trim(); | ||
// Replace alpha representations | ||
parts[4] = this.replaceAlphaMonths(parts[4]); | ||
parts[5] = this.replaceAlphaDays(parts[5]); | ||
// Check that part only contain legal characters ^[0-9-,]+$ | ||
if( reValidCron.test(part) ) { | ||
throw new TypeError("CronPattern: configuration entry " + (i + 1) + " (" + part + ") contains illegal characters."); | ||
} | ||
} | ||
// Check part content | ||
this.throwAtIllegalCharacters(parts); | ||
@@ -82,2 +78,3 @@ // Parse parts into arrays, validates as we go | ||
* Convert current part (seconds/minutes etc) to an array of 1 or 0 depending on if the part is about to trigger a run or not. | ||
* @private | ||
* | ||
@@ -92,5 +89,2 @@ * @param {CronPatternPart} type - Seconds/minutes etc | ||
split, | ||
lower, | ||
upper, | ||
steps, | ||
arr = this[type]; | ||
@@ -106,3 +100,3 @@ | ||
// Recurse into comma separated entries | ||
// Handle separated entries (,) by recursion | ||
split = conf.split(","); | ||
@@ -113,84 +107,166 @@ if( split.length > 1 ) { | ||
} | ||
return; | ||
} | ||
// Didn't need to recurse, determine if this is a range, steps or a number | ||
// - Got a range | ||
if( conf.indexOf("-") !== -1 ) { | ||
// Handle range (-) | ||
} else if( conf.indexOf("-") !== -1 ) { | ||
this.handleRange(conf, type, valueIndexOffset); | ||
split = conf.split("-"); | ||
// Handle stepping (/) | ||
} else if( conf.indexOf("/") !== -1 ) { | ||
this.handleStepping(conf, type, valueIndexOffset); | ||
if( split.length !== 2 ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal range: '" + conf + "'"); | ||
} | ||
// Handle pure number | ||
} else { | ||
this.handleNumber(conf, type, valueIndexOffset); | ||
} | ||
lower = parseInt(split[0], 10) + valueIndexOffset; | ||
upper = parseInt(split[1], 10) + valueIndexOffset; | ||
}; | ||
if( isNaN(lower) ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)"); | ||
} else if( isNaN(upper) ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)"); | ||
/** | ||
* After converting JAN-DEC, SUN-SAT only 0-9 * , / - are allowed, throw if anything else pops up | ||
* @private | ||
* | ||
* @param {string[]} parts - Each part split as strings | ||
*/ | ||
CronPattern.prototype.throwAtIllegalCharacters = function (parts) { | ||
let reValidCron = /[^/*0-9,-]+/; | ||
for(let i = 0; i < parts.length; i++) { | ||
if( reValidCron.test(parts[i]) ) { | ||
throw new TypeError("CronPattern: configuration entry " + i + " (" + parts[i] + ") contains illegal characters."); | ||
} | ||
} | ||
}; | ||
// Check that value is within range | ||
if( lower < 0 || upper >= arr.length ) { | ||
throw new TypeError("CronPattern: Value out of range: '" + conf + "'"); | ||
} | ||
/** | ||
* Nothing but a number left, handle that | ||
* @private | ||
* | ||
* @param {string} conf - Current part, expected to be a number, as a string | ||
* @param {string} type - One of "seconds", "minutes" etc | ||
* @param {number} valueIndexOffset - -1 for day of month, and month, as they start at 1. 0 for seconds, hours, minutes | ||
*/ | ||
CronPattern.prototype.handleNumber = function (conf, type, valueIndexOffset) { | ||
let i = (parseInt(conf, 10) + valueIndexOffset); | ||
// | ||
if( lower > upper ) { | ||
throw new TypeError("CronPattern: From value is larger than to value: '" + conf + "'"); | ||
} | ||
if( i < 0 || i >= this[type].length ) { | ||
throw new TypeError("CronPattern: " + type + " value out of range: '" + conf + "'"); | ||
} | ||
for( i = lower; i <= upper; i++ ) { | ||
arr[(i + valueIndexOffset)] = 1; | ||
} | ||
this[type][i] = 1; | ||
}; | ||
// - Got stepping | ||
} else if( conf.indexOf("/") !== -1 ) { | ||
split = conf.split("/"); | ||
if( split.length !== 2 ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal stepping: '" + conf + "'"); | ||
} | ||
/** | ||
* Take care of ranges (e.g. 1-20) | ||
* @private | ||
* | ||
* @param {string} conf - Current part, expected to be a string like 1-20 | ||
* @param {string} type - One of "seconds", "minutes" etc | ||
* @param {number} valueIndexOffset - -1 for day of month, and month, as they start at 1. 0 for seconds, hours, minutes | ||
*/ | ||
CronPattern.prototype.handleRange = function (conf, type, valueIndexOffset) { | ||
let split = conf.split("-"); | ||
if( split[0] !== "*" ) { | ||
throw new TypeError("CronPattern: Syntax error, left part of / needs to be * : '" + conf + "'"); | ||
} | ||
if( split.length !== 2 ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal range: '" + conf + "'"); | ||
} | ||
steps = parseInt(split[1], 10); | ||
let lower = parseInt(split[0], 10) + valueIndexOffset, | ||
upper = parseInt(split[1], 10) + valueIndexOffset; | ||
if( isNaN(steps) ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)"); | ||
} | ||
if( isNaN(lower) ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)"); | ||
} else if( isNaN(upper) ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)"); | ||
} | ||
if( steps === 0 ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal stepping: 0"); | ||
} | ||
// Check that value is within range | ||
if( lower < 0 || upper >= this[type].length ) { | ||
throw new TypeError("CronPattern: Value out of range: '" + conf + "'"); | ||
} | ||
if( steps > arr.length ) { | ||
throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+arr.length+")"); | ||
} | ||
// | ||
if( lower > upper ) { | ||
throw new TypeError("CronPattern: From value is larger than to value: '" + conf + "'"); | ||
} | ||
for( i = 0; i < arr.length; i+= steps ) { | ||
arr[(i + valueIndexOffset)] = 1; | ||
} | ||
for( let i = lower; i <= upper; i++ ) { | ||
this[type][(i + valueIndexOffset)] = 1; | ||
} | ||
}; | ||
// - Got a number | ||
} else { | ||
/** | ||
* Handle stepping (e.g. * / 14) | ||
* @private | ||
* | ||
* @param {string} conf - Current part, expected to be a string like * /20 (without the space) | ||
* @param {string} type - One of "seconds", "minutes" etc | ||
* @param {number} valueIndexOffset - -1 for day of month, and month, as they start at 1. 0 for seconds, hours, minutes | ||
*/ | ||
CronPattern.prototype.handleStepping = function (conf, type, valueIndexOffset) { | ||
i = (parseInt(conf, 10) + valueIndexOffset); | ||
let split = conf.split("/"); | ||
if( i < 0 || i >= arr.length ) { | ||
throw new TypeError("CronPattern: " + type + " value out of range: '" + conf + "'"); | ||
} | ||
if( split.length !== 2 ) { | ||
throw new TypeError("CronPattern: Syntax error, illegal stepping: '" + conf + "'"); | ||
} | ||
arr[i] = 1; | ||
if( split[0] !== "*" ) { | ||
throw new TypeError("CronPattern: Syntax error, left part of / needs to be * : '" + conf + "'"); | ||
} | ||
let steps = parseInt(split[1], 10); | ||
if( isNaN(steps) ) throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)"); | ||
if( steps === 0 ) throw new TypeError("CronPattern: Syntax error, illegal stepping: 0"); | ||
if( steps > this[type].length ) throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[type].length+")"); | ||
for( let i = 0; i < this[type].length; i+= steps ) { | ||
this[type][(i + valueIndexOffset)] = 1; | ||
} | ||
}; | ||
/** | ||
* Replace day name with day numbers | ||
* @private | ||
* | ||
* @param {string} conf - Current part, expected to be a string that might contain sun,mon etc. | ||
* | ||
* @returns {string} - conf with 0 instead of sun etc. | ||
*/ | ||
CronPattern.prototype.replaceAlphaDays = function (conf) { | ||
return conf | ||
.replace(/sun/gi, "0") | ||
.replace(/mon/gi, "1") | ||
.replace(/tue/gi, "2") | ||
.replace(/wed/gi, "3") | ||
.replace(/thu/gi, "4") | ||
.replace(/fri/gi, "5") | ||
.replace(/sat/gi, "6"); | ||
}; | ||
/** | ||
* Replace month name with month numbers | ||
* @private | ||
* | ||
* @param {string} conf - Current part, expected to be a string that might contain jan,feb etc. | ||
* | ||
* @returns {string} - conf with 0 instead of sun etc. | ||
*/ | ||
CronPattern.prototype.replaceAlphaMonths = function (conf) { | ||
return conf | ||
.replace(/jan/gi, "1") | ||
.replace(/feb/gi, "2") | ||
.replace(/mar/gi, "3") | ||
.replace(/apr/gi, "4") | ||
.replace(/may/gi, "5") | ||
.replace(/jun/gi, "6") | ||
.replace(/jul/gi, "7") | ||
.replace(/aug/gi, "8") | ||
.replace(/sep/gi, "9") | ||
.replace(/oct/gi, "10") | ||
.replace(/nov/gi, "11") | ||
.replace(/dec/gi, "12"); | ||
}; | ||
export { CronPattern }; |
@@ -106,6 +106,7 @@ export default Cron; | ||
* Return previous run time | ||
* @public | ||
* | ||
* @returns {Date | null} - Previous run time | ||
*/ | ||
previous(): Date | null; | ||
public previous(): Date | null; | ||
private _next; | ||
@@ -112,0 +113,0 @@ /** |
@@ -31,14 +31,10 @@ export type CronPatternPart = "seconds" | "minutes" | "hours" | "days" | "months" | "daysOfWeek"; | ||
daysOfWeek: any[]; | ||
/** | ||
* Parse current pattern, will raise an error on failure | ||
*/ | ||
parse(): void; | ||
/** | ||
* Convert current part (seconds/minutes etc) to an array of 1 or 0 depending on if the part is about to trigger a run or not. | ||
* | ||
* @param {CronPatternPart} type - Seconds/minutes etc | ||
* @param {string} conf - Current pattern part - *, 0-1 etc | ||
* @param {CronIndexOffset} valueIndexOffset - 0 or -1. 0 for seconds,minutes, hours as they start on 1. -1 on days and months, as the start on 0 | ||
*/ | ||
partToArray(type: CronPatternPart, conf: string, valueIndexOffset: CronIndexOffset): void; | ||
private parse; | ||
private partToArray; | ||
private throwAtIllegalCharacters; | ||
private handleNumber; | ||
private handleRange; | ||
private handleStepping; | ||
private replaceAlphaDays; | ||
private replaceAlphaMonths; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
87228
1648
203