UNPKG

quartzcron

Version:

version: `0.1.0` [CHANGELOG](https://github.com/fedeghe/quartzcron/blob/master/CHANGELOG.md)

4 lines 8.21 kB
/* quartzcron (v.0.1.0) */ const{monthEnds, labels, rx, errors, bounds}=require('./constants.js'),{daysLabels2Numbers}=require('./utils.js');const isLeap=y=> !(y % 4)&&(!!(y % 100)|| !(y % 400));const lastMonthDay=(y, m, wd)=>{let ret, day;if(m===1){ret=isLeap(y)? 29:monthEnds[m];}else{ret=monthEnds[m];}if(wd){const da=new Date(Date.UTC(y,m,ret,0,0));day=da.getUTCDay();if(day==6){return ret-1;}if(day==0){return ret-2;}}return ret;};const nDaysBeforeEndOfMonth=(n, y, m)=>{const end=lastMonthDay(y, m), pot=end-n;if(pot < 1)throw new Error(errors.notEnoughDays);return pot;};const nDayOfMonth=(n, wd, y, m)=>{if(wd < 0 || wd > 6)throw new Error(errors.nonWeekday);if(n < 0 || n > 5)throw new Error(errors.monthsOutOfBounds);const end=lastMonthDay(y, m), da=new Date(Date.UTC(y,m,1,0,0)), first=da.getUTCDay(), distance=(first-1+7)%7, firstTarget=(wd+7-distance)% 7, nthTarget=(n-1)*7+firstTarget;if(nthTarget > end)throw new Error(errors.monthOutOfBounds);return nthTarget;};const getRangeSolver=({labelTransformer=v=> v, bounds, rx})=> v=>{let vstr=`${v}`, spl, mat;if(v==='?')return null;if(vstr.startsWith('*')){vstr=vstr.replace('*', `${bounds.min}-${bounds.max}`);}vstr=labelTransformer(vstr);if(vstr.match(/^\d*$/)){return[parseInt(vstr, 10)];}spl=vstr.split(/,/);mat=spl.map(s=> s.match(/^((\d*)|(\d*)\/(\d*))$/)).filter(Boolean);if(spl.length===mat.length){return mat.reduce((acc, r)=>{let p=parseInt(r[2], 10);if(r[2]){if(p <=bounds.max)acc.push(p);}else{let cursor=parseInt(r[3], 10);const every=parseInt(r[4], 10);while(cursor <=bounds.max){acc.push(cursor);cursor+=every;}}return acc;},[]).sort((a, b)=> a > b ? 1:-1);}const range=vstr.match(rx);if(range){const min=parseInt(range[1],10), max=parseInt(range[2],10), cadence=parseInt(range[4],10);let ret=[];if(cadence){for(let i=min;i<=max;i+=cadence){ret.push(i);}}else{ret=Array.from({length:max-min+1},(_, i)=> i+min);}return ret;}return null;};const getSpecialSolver=solvers=>(y, m, val)=>{const d=new Date(Date.UTC(y, m-1, 1, 0, 0)), lastDate=lastMonthDay(y, m-1), allDays=Array.from({length:lastDate},(_,i)=> i+1);for(var i=0, l=solvers.length, r;i < l;i++){r=solvers[i]({y, m, val, d, allDays, lastDate});if(r.length)return r;}return[];};const dom_solvers=[({val, allDays})=> val.match(/^(\*)$/)? allDays:[],({val, lastDate})=>{const mat=val.match(/^([1-9]|1[0-9]|2[0-9]|3[01]|\*)\/(([1-9]|1[0-9]|2[0-9]|3[01]|\*))$/);let res=[];if(mat){let start=parseInt(mat[1], 10), step=parseInt(mat[2], 10);while(start <=lastDate){res.push(start);start+=step;}}return res;},({val, lastDate})=>{const mat=val.match(/^([1-9]|1[0-9]|2[0-9]|3[01]|\*)\-(([1-9]|1[0-9]|2[0-9]|3[01]|\*))$/);let res=[];if(mat){let start=parseInt(mat[1], 10), end=parseInt(mat[2], 10);while(start <=end && start<=lastDate){res.push(start);start+=1;}}return res;},({val, lastDate})=>{const mat=val.match(/^([1-9]|1[0-9]|2[0-9]|3[01])$/);if(mat){var ret=parseInt(mat[1], 10);if(ret <=lastDate)return[ret];}return[];},({val, lastDate})=>{const spl=val.split(/,/), mat=spl.map(s=> s.match(/^(([1-9]|1[0-9]|2[0-9]|3[01])|([1-9]|1[0-9]|2[0-9]|3[01])\/([1-9]|1[0-9]|2[0-9]|3[01]))$/)).filter(Boolean);if(spl.length===mat.length){return mat.reduce((acc, r)=>{let v2=parseInt(r[2], 10);if(typeof r[2]!=='undefined'){if(v2 <=lastDate)acc.push(v2);}else{let cursor=parseInt(r[3], 10);const every=parseInt(r[4], 10);while(cursor <=lastDate){acc.push(cursor);cursor+=every;}}return acc;},[]).sort((a, b)=> a > b ? 1:-1);}return[];},({val, lastDate})=>{const vals=val.match(rx.ranged['md-md/md']), res=[];if(vals){const add=Math.min(parseInt(vals[3],10), lastDate);let tmp=Math.min(parseInt(vals[1],10),lastDate), lim=Math.min(parseInt(vals[2],10), lastDate);while(tmp <=lim){res.push(tmp);tmp+=add;}}return res;},({val, lastDate})=> val.match(rx.dumb.L)?[lastDate]:[],({val, lastDate, d})=>{if(val.match(rx.dumb.LW)){d.setUTCDate(lastDate);let res=d.getUTCDay(), min=0;while(`${(res-min+7)%7}`.match(rx.dumb['0OR6'])){min++;}return[lastDate-min];}return[];},({val, lastDate, d})=>{let mat=val.match(rx.ranged.mdW);if(mat){let v=parseInt(mat[1], 10), res;d.setUTCDate(v);res=d.getUTCDay();if(v===1){if(res===6)return[3];if(res===0)return[2];return[1];}if(v===lastDate){if(res===6)return[lastDate-1];if(res===0)return[lastDate-2];return[lastDate];}if(res===0)return[v+1];if(res===6)return[v-1];return[v];}return[];},({val, lastDate})=>{const vals=val.match(rx.ranged['L-md']);if(vals){const last=lastDate-parseInt(vals[1]);return last> 0 ?[last]:[];}return[];},];const solve_dom=getSpecialSolver(dom_solvers);const dow_solvers=[({val, allDays})=> val.match(rx.dumb.astrx)? allDays:[],({val, d, lastDate})=>{const mat=val.match(rx.ranged['wdOR*/wd']);let res=[];if(mat){const fromFirstWd=mat[1]==='*' ? 1:parseInt(mat[1], 10), step=parseInt(mat[2]);let firstDayWd=d.getUTCDay()+1, toAddDate=1;while(firstDayWd !==fromFirstWd){firstDayWd=1+firstDayWd%7;toAddDate++;}while(toAddDate <=lastDate){res.push(toAddDate);toAddDate+=step;}}return res;},({val, d, lastDate})=>{let vals=daysLabels2Numbers(val).split(rx.dumb.comma);const firstDayWd=d.getUTCDay()+1, res=[], max=7;let mat=vals.map(s=> s.match(rx.ranged['wdORwd/wd'])).filter(Boolean);if(mat.length===vals.length){vals=mat.reduce((acc, r)=>{let v2=parseInt(r[2], 10);if(typeof r[2]!=='undefined'){acc.push(v2);}else{let cursor=parseInt(r[3], 10);const every=parseInt(r[4], 10);while(cursor <=max){acc.push(cursor);cursor=every+cursor;}}return acc;},[]).map(v=> v.toString());}if(vals.every(v=> v.match(rx.ranged.wd))){let cursor=firstDayWd, toAddDate=1;while(toAddDate <=lastDate){if(vals.includes(`${cursor}`))res.push(toAddDate);cursor=1+cursor%7;toAddDate+=1;}}return res;},({val, d, lastDate})=>{const mat=daysLabels2Numbers(val).match(rx.ranged['wd-wd']);let res=[];if(mat){let cursor=parseInt(mat[2], 10), firstDayWd=d.getUTCDay()+1, rangeFilled=false, toAddDate=1;const to=parseInt(mat[3], 10), range=[cursor];while(!rangeFilled){cursor=1+cursor%7;range.push(cursor);rangeFilled=cursor===to;}while(toAddDate <=lastDate){if(range.includes(firstDayWd))res.push(toAddDate);firstDayWd=1+firstDayWd%7;toAddDate+=1;}}return res;},({val, d, lastDate})=>{const mat=daysLabels2Numbers(val).match(rx.ranged['wd-wd/wd']), res=[];let firstDayWd=d.getUTCDay()+1, toAddDate=1;if(mat){const to=parseInt(mat[3], 10), cadence=parseInt(mat[4], 10);let rangeFilled=false, cursor=parseInt(mat[2], 10), range=[cursor];while(!rangeFilled){cursor=(1+cursor)%7;range.push(cursor);rangeFilled=cursor===to;}range=range.filter((_,i)=>{return i===0 || i % cadence===0;});while(toAddDate <=lastDate){if(range.includes(firstDayWd))res.push(toAddDate);firstDayWd=1+firstDayWd%7;toAddDate+=1;}}return res;},({val, d, lastDate})=>{const mat=val.match(rx.ranged.wdL);let res=[], trg=lastDate;d.setUTCDate(lastDate);let cursorDay=d.getUTCDay()+1;if(mat){let trgWd=parseInt(mat[1], 10);while(cursorDay !==trgWd){cursorDay=cursorDay-1>0 ? cursorDay-1:7;trg--;}return[trg];}return res;},({val, d, lastDate})=>{const mat=val.match(rx.ranged['wd#wdn']), res=[];d.setUTCDate(1);let cursorDate=1;cursorDay=d.getUTCDay()+1;if(mat){const wd=parseInt(mat[1], 10), n=parseInt(mat[2], 10);while(cursorDay !==wd){cursorDay=cursorDay+1 > 7 ? 1:cursorDay+1;cursorDate++;}let ret=cursorDate+(n-1)*7;return ret <=lastDate ?[ret]:[];}return res;},];const solve_dow=getSpecialSolver(dow_solvers);const solve_0_59_ranges=getRangeSolver({bounds:bounds.seconds, rx:rx.ranges.wildRangeCadence}), solve_hours_ranges=getRangeSolver({bounds:bounds.hour, rx:rx.ranges.wildRangeCadence}), solve_month_ranges=getRangeSolver({bounds:bounds.month, labelTransformer:vstr=> vstr.match(rx.next.hasMonths)? labels.months.reduce((acc, day, i)=> acc.replace(day, i+1), vstr):vstr, rx:rx.ranges.wildRangeCadence}), solve_year_ranges=getRangeSolver({bounds:bounds.year, rx:rx.ranges.wildRangeCadence}), solve_week_ranges=getRangeSolver({bounds:bounds.week, labelTransformer:vstr=> vstr.match(rx.next.hasWeekdays)? labels.days.reduce((acc, day, i)=> acc.replace(day, i+1), vstr):vstr, rx:rx.ranges.wildRangeCadence});module.exports={isLeap, lastMonthDay, nDaysBeforeEndOfMonth, nDayOfMonth, solve_0_59_ranges, solve_year_ranges, solve_month_ranges, solve_week_ranges, solve_hours_ranges, solve_dom, solve_dow};