collection.findAndModify({_id: job._id, status: {$in: [STATUS.RUNNING, STATUS.SCHEDULED]}}, [['_id', 1]], update, function(err, job){ job = job && job.ok ? job.value : null; if (err) { log.e('Couldn\'t update a job: %j', err); } else if (!job) { // ignore } else if (job.status === STATUS.RUNNING) { log.i('The job is running on another server, won\'t start it here'); } else if (job.status === STATUS.SCHEDULED) { this.process(job); if (job.schedule) { var schedule = typeof job.schedule === 'string' ? later.parse.text(job.schedule) : job.schedule, nextFrom = new Date(job.next); var next = later.schedule(schedule).next(2, nextFrom); if (next && next.length > 1) { if (job.strict === null) { // for strict jobs we're going to repeat all missed tasks up to current date after restart // for non-strict ones, we want to start from current date while (next[1].getTime() < Date.now()) { next = later.schedule(schedule).next(2, next[1]); if (next.length < 2) { return; } } } new Job(job.name, job.data, this).schedule(job.schedule, job.strict, null, next[1].getTime()); } } } }.bind(this));
this.collection.findAndModify({_id: job._json._id, status: {$in: [STATUS.RUNNING, STATUS.SCHEDULED]}}, [['_id', 1]], update, (err, res) => { if (err) { log.e('Couldn\'t update a job: %j', err); } else if (!res || !res.value) { // ignore } else if (res.value.status === STATUS.RUNNING) { log.i('The job is running on another server, won\'t start it here'); } else if (res.value.status === STATUS.SCHEDULED) { this.start(job); if (job.scheduleObj) { var schedule = typeof job.scheduleObj === 'string' ? later.parse.text(job.scheduleObj) : job.scheduleObj, nextFrom = new Date(job.next); var next = later.schedule(schedule).next(2, nextFrom); if (next && next.length > 1) { if (job.strict !== null) { // for strict jobs we're going to repeat all missed tasks up to current date after restart // for non-strict ones, we want to start from current date while (next[1].getTime() < Date.now()) { next = later.schedule(schedule).next(2, next[1]); if (next.length < 2) { return; } } } job.schedule(job.scheduleObj, job.strict, next[1].getTime()); } } } });
function getSchedule(config) { // fetch a schedule based on the configuration, parsing it as a "cron" // or "text" statement see: // http://bunkat.github.io/later/parsers.html if (!config) return; if (config.text_expression) { // text expression takes precedence over cron return later.schedule(later.parse.text(config.text_expression)); } if (config.cron) { return later.schedule(later.parse.cron(config.cron)); } }
function getNextRun( schedule ) { var s = later.schedule( later.parse.cron( schedule.recurrence ) ); var args = [ 1 ]; var now = moment(); // If the schedule has a start time, ensure the next run time is after that start time if ( schedule.hasOwnProperty( 'start' ) && moment( schedule.start ).isAfter( now ) ) { args.push( schedule.start ); } else { // The later module has a bug where it will calculate next to be now if there are < 1 second on the current time stamp args.push( now.add( 1, 'second' ).toISOString() ); } // gets the next run time of the schedule and clamps milli/seconds to zero var nextRun = moment( s.next.apply( s, args ).toISOString() ).millisecond( 0 ).seconds( 0 ); // if schedule has an end time, and next time is beyond that point, cancel the next run if ( schedule.hasOwnProperty( 'end' ) && moment( schedule.end ).isBefore( nextRun ) ) { return null; } return nextRun; }
function parseCron(cronExp) { let parts = cronExp.trim().split(/\s+/); if (parts.length === 5) parts.unshift("*"); return later.schedule(later.parse.cron(parts.join(" "), true)); }
return Promise.try(function() { // See if we are meant to run on an interval self.parsedSchedule = null; if (this.schedule) { self.parsedSchedule = later.parse.text(this.schedule); } else if (this.cron) { self.parsedSchedule = later.parse.cron(this.cron); } // If not, we're done already - stand by until manually queued. if (!self.parsedSchedule) { return true; } // NOTE: We can't do !== -1 because CRON parsing doesn't set it: // > JSON.stringify(later.parse.cron('* */15 * * * *', true)); // '{"schedules":[{"m":[0,15,30,45]}],"exceptions":[]}' // > JSON.stringify(later.parse.text('every 15 mins')); // '{"schedules":[{"m":[0,15,30,45]}],"exceptions":[],"error":-1}' if (self.parsedSchedule.error >= 0) { throw new Error('Invalid task schedule at char ' + self.parsedSchedule.error); } // See if a task entry is already scheduled for this task - use the schedule as the key var taskEntryKey = keyForSchedule(self.parsedSchedule); crone.logger('Next run: ' + later.schedule(self.parsedSchedule).next(1).schedule.next(2)); self.emit('scheduled', self, taskEntry); var taskEntry = new TaskEntry(); taskEntry.task = self; self.emit('before', self, taskEntry); });
function calculatePrevious(timeDescription) { var parsed; var s; var next; parsed = later.parse.text(timeDescription); s = later.schedule(parsed); next = s.prev(1); return new Date(next); }
function compileSchedule(val){ compiledSchedule = later.parse.text(val); if(~compiledSchedule.error){ scheduleError = "Error in schedule near: " + val.substr(compiledSchedule.error) + '\n For help on supported text structures, see http://bunkat.github.io/later/parsers.html#text.'; nextRunTime = undefined; } else { scheduleError = undefined; nextRunTime = later.schedule(compiledSchedule).next().getTime(); } }
crons.forEach(cron => { let parts = cron.cronExpression.split(' '); let hours = parts[2]; if (!isNaN(parseInt(hours))) { let allHours = hours.split('/'); let tz = settings.defaultTimeZone || 'America/Los_Angeles'; var offset = momentService.tz.zone(tz).offset(new Date()); if (offset) { offset /= 60; let start = parseInt(allHours[0]); allHours[0] = start + offset >= 24 ? start : start + offset; parts[2] = allHours.join('/'); } } let schedule = later.parse.cron(parts.join(' '), true); let nextRun = later.schedule(schedule).next(1); if (nextRun) { nextTimes.push(later.schedule(schedule).next(1).getTime()); } });
geddy.model.Task.first(params.id, function(err, task) { task.updateProperties(params); if (!task.isValid()) { self.respond({params: params, success: false, errors: task.errors}, {format: 'json'}); } else { // If completing a repeated task if (task.complete && task.repeat) { console.log('Creating repeat task.'); var m = moment(task.dueDate); console.log(m); var start = m.toDate(); console.log(start); var sched = later.parse.text(task.repeat); console.log(sched); console.log(sched.schedules); var newDueDate = later.schedule(sched).next(2, start); console.log(newDueDate[newDueDate.length - 1]); var taskParams = {groupId: task.groupId, name: task.name, complete:false, repeat: task.repeat, dueDate: newDueDate[newDueDate.length - 1]}; var newTask = geddy.model.Task.create(taskParams); if (!newTask.isValid()) { console.log('Invalid task params.'); } newTask.save(function(err, data) { if (err) { console.log('Error creating repeat task.'); } else { console.log('Repeat task created and saved.'); geddy.io.sockets.in(task.groupId).emit('taskCreated', newTask); } }); } task.save(function(err, data) { if (err) { self.respond({params: params, success: false, errors: err}, {format: 'json'}); } else { geddy.io.sockets.in(task.groupId).emit('taskUpdated', task); self.respond({params: params, success: true}, {format: 'json'}); } }); } });
events.forEach( schedEvent => { if(!schedEvent.isValid) { Log.warn( { eventName : schedEvent.name }, 'Invalid scheduled event entry'); return; } Log.debug( { eventName : schedEvent.name, schedule : this.moduleConfig.events[schedEvent.name].schedule, action : schedEvent.action, next : schedEvent.schedule.sched ? moment(later.schedule(schedEvent.schedule.sched).next(1)).format('ddd, MMM Do, YYYY @ h:m:ss a') : 'N/A', }, 'Scheduled event loaded' ); if(schedEvent.schedule.sched) { this.eventTimers.push(later.setInterval( () => { self.performAction(schedEvent, 'Schedule'); }, schedEvent.schedule.sched)); } if(schedEvent.schedule.watchFile) { const watcher = sane( paths.dirname(schedEvent.schedule.watchFile), { glob : `**/${paths.basename(schedEvent.schedule.watchFile)}` } ); // :TODO: should track watched files & stop watching @ shutdown? [ 'change', 'add', 'delete' ].forEach(event => { watcher.on(event, (fileName, fileRoot) => { const eventPath = paths.join(fileRoot, fileName); if(schedEvent.schedule.watchFile === eventPath) { self.performAction(schedEvent, `Watch file: ${eventPath}`); } }); }); fse.exists(schedEvent.schedule.watchFile, exists => { if(exists) { self.performAction(schedEvent, `Watch file: ${schedEvent.schedule.watchFile}`); } }); } });
function run(){ if(scriptError || scheduleError) return; var nextTwo = later.schedule(compiledSchedule).next(2); lastRunTime = nextRunTime; nextRunTime = nextTwo[1].getTime(); // index 0 is the current one try{ lastResult = compiledScript.runInNewContext({ require: require, console: console }); } catch(err){ scriptError = err.stack; } }
return new Promise(function(resolve, reject){ var token; var access_token; later.date.localTime(); console.log("Now:" + new Date()); var sched = later.parse.recur().every(1).hour(); next = later.schedule(sched).next(10); console.log(next); var timer = later.setInterval(test, sched); setTimeout(test, 1000); function test() { console.log(new Date()); var options = { hostname: 'api.weixin.qq.com', path: '/cgi-bin/token?grant_type=client_credential&appid=' + appID + '&secret=' + appSecret }; var req = https.get(options, function (res) { console.log("statusCode: ", res.statusCode); console.log("headers: ", res.headers); var bodyChunks = ''; res.on('data', function (chunk) { bodyChunks += chunk; }); res.on('end', function () { var body = JSON.parse(bodyChunks); console.log("body:",body); if (body.access_token) { access_token = body.access_token; resolve(access_token); //saveAccessToken(access_token); console.log("access_token=",access_token); } else { console.dir(body); //在有调试工具的浏览器上支持较好,各大浏览器均支持此功能 } }); }); req.on('error', function (e) { console.log('ERROR: ' + e.message); }); } });
validateSchedule: function(schedule) { if (typeof schedule != 'object' || typeof schedule.schedules == 'undefined') { if (_.isEmpty(schedule) || (schedule instanceof Array && schedule.length == 0) || typeof schedule == 'string') return false; schedule = {schedules: schedule}; } // attempt to compile schedule in later.js try { later.schedule(schedule); } catch (e) { return false; } return true; },
module.config.events.forEach((event) => { event = { checkDelay: 30, checkWindow: Math.round((event.checkDelay || 30) * 1.5), callRecipient: null, callDelay: 0, ...event, lastCallAt: 0 }; logger.info(`Setting up...`, { eventId: event.id, nextEventAt: later.schedule(event.schedule).next(1) }); later.setInterval(scheduleEventCheck.bind(null, event), event.schedule); });
schedule (schedule, strict, nextTime) { this._json.schedule = schedule; if (strict) { this._json.strict = strict; } if (nextTime) { this._json.next = nextTime; } else { schedule = typeof schedule === 'string' ? later.parse.text(schedule) : schedule; var next = later.schedule(schedule).next(1); if (!next) { return null; } this._json.next = next.getTime(); } return this._save(); }
runSched = function (msg, sched) { //Only do anything if the schedule has a next event if (later.schedule(sched).next(1)) { runningSchedules[msg.later.id] = later.setTimeout(function () { //Run this again to schedule the next event /*IMPORTANT that this is done before the message is sent to avoid a race condition in the case this message triggers a downstream node to cancel the flow*/ runSched(msg, sched); //Send out the message msg.later.count += 1; node.send(msg); }, sched); debug('Started timer for schedule : ' + msg.later.id); } else { //This schedule has finished, remove any references to previous timers debug('Schedule has ended : ' + msg.later.id); delete runningSchedules[msg.later.id]; } },
var _requestHandler = function(request, response) { var occurrences = later.schedule(schedule); response.writeHead(200, {'Content-Type': 'text/plain'}); response.write('waiting...\n'); response.write('next notification at: ' + occurrences.next(1, new Date())); response.write('\n\nmost recent meh notification:\n'); fs.readFile(mehFileName, {encoding: 'utf-8'}, function (error, data) { if (!error) { // parse the file data to a JSON object then pretty print it to the response var jsonString = JSON.parse(data); response.write(JSON.stringify(jsonString, null, 4)); } else { response.write('failed to read ' + mehFileName + '!'); } // end the response in the callback response.end(); }); };
this.schedule = function(schedule, strict, clb, nextTime) { if (typeof strict === 'function') { clb = strict; strict = null; } json.schedule = schedule; json.strict = typeof strict === 'undefined' ? null : strict; if (nextTime) { json.next = nextTime; } else { schedule = typeof schedule === 'string' ? later.parse.text(schedule) : schedule; var next = later.schedule(schedule).next(1); if (!next) { return null; } json.next = next.getTime(); } save(clb); return this; };
execute().finally(() => { logger.info('Waiting for next schedule run ' + later.schedule(scheduler).next(1)); logger.info('==============================================================='); }).subscribe();
return new Promise((resolve, reject) => { try { this._json.modified = Date.now(); var query, update, clb = (err, res) => { if (err) { if (this._errorCount++ < MAXIMUM_SAVE_ERRORS) { log.w('Error while saving job: %j', err); setTimeout(() => { this._save(set).then(resolve.bind(null, set), reject); }, 1000); } else { log.e('Error while saving job: %j', err); reject(err); } } else if (res.result.nModified === 0) { log.e('Job %s has been changed while doing _save: %j / setting %j for query %j', this._id, this._json, update, query); reject('Job cannot be found while doing _save'); } else { resolve(set); } if (this.isSub && this.parent) { this.parent._subSaved(this); } }; if (this._replace) { query = {status: STATUS.SCHEDULED, name: this.name}; if (this.data) { query.data = this.data; } if (this._json.schedule) { let schedule = typeof this._json.schedule === 'string' ? later.parse.text(this._json.schedule) : this._json.schedule, prev = later.schedule(schedule).prev(1); log.i('replacing job %j with', query, this._json); this.db().collection('jobs').find(query).toArray((err, jobs) => { if (err) { log.e('job replacement error when looking for existing jobs to replace', err); this.db().collection('jobs').save(this._json, clb); } else if (jobs && jobs.length) { try { let last = jobs.sort((a, b) => b.next - a.next)[0]; let others = jobs.filter(a => a !== last); if (others.length) { log.i('found %d jobs with %j, going to cancel %j', jobs.length, query, others.map(j => j._id)); Promise.all(others.map(j => { return require('./index.js').create(j).cancel(this.db(), false); })); // this.db().collection('jobs').update({_id: {$in: others.map(j => j._id)}}, {$set: {status: STATUS.CANCELLED}}, {multi: true}, log.logdb('')); } if (last.schedule === this._json.schedule && last.next > prev.getTime()) { // just do nothing log.i('last job is scheduled correctly, won\'t replace anything for %j: current %j, won\'t replace to %j', query, new Date(last.next), new Date(this.next)); resolve(set); } else { log.i('replacing last job %j with %j', last, this._json); this.db().collection('jobs').findAndModify(query, [['_id', 1]], {$set: this._json}, {new: true}, (err, job) => { if (err) { log.e('job replacement error, saving new job', err, job); this.db().collection('jobs').save(this._json, clb); } else if (job && !job.value){ log.i('no job found to replace, saving new job', err, job); this.db().collection('jobs').save(this._json, clb); } else { log.i('job replacing done', job.value); resolve(set); } }); } }catch(e) { log.e(e, e.stack); } } else { log.i('no jobs found to replace for %j, saving new one', query); this.db().collection('jobs').save(this._json, clb); } }); } else { this.db().collection('jobs').findAndModify(query, [['_id', 1]], {$set: this._json}, {new: true}, (err, job) => { if (err) { log.e('job replacement error, saving new job', err, job); this.db().collection('jobs').save(this._json, clb); } else if (job && !job.value){ log.i('no job found to replace, saving new job', err, job); this.db().collection('jobs').save(this._json, clb); } else { log.i('job replacing done', job.value); resolve(set); } }); } } else if (this._json._id) { if (set) { for (let k in set) { if (k !== '_id') { this._json[k] = set[k]; } } } if (this._isSub()) { query = {_id: this._json._id, 'subs.idx': this._json.idx}; if (set) { update = {$set: {'subs.$.modified': this._json.modified}}; for (let k in set) { update.$set['subs.$.' + k] = set[k]; } } else { update = {$set: {'subs.$': this._json}}; } } else { query = {_id: this._json._id}; update = {$set: set || this._json}; update.$set.modified = this._json.modified; } delete update.$set._id; log.d('saving %j: %j', query, update); this.db().collection('jobs').updateOne(query, update, clb); } else { log.d('saving %j', this._json); this.db().collection('jobs').save(this._json, clb); } }catch(e) { log.e(e, e.stack); throw e; } }).then(() => { this._replace = false; return set; });
var later = require('later'); var sched = later.parse.text('every 5 mins'), occurrences = later.schedule(sched).next(10); for(var i=0;i<10;i++){ console.log(occurrences[i]); }
next: function(count) { return later.schedule(this.s).next(count); },
// console.log(occurrences[i]); // } // var cron = later.parse.cron('5 * * * *'); // // occurrences = later.schedule(demo2_b).next(3); // for(var i = 0; i < occurrences.length; i++) { // console.log(occurrences[i]); // } // // 时间控制API // // later.schedule(schedule).next(count, start, end): 取下N个有效时间点 // later.schedule(schedule).prev(count, start, end): 取上N个有效时间点 // later.schedule(schedule).nextRange(count, start, end): 取下N个有效时间段 // later.schedule(schedule).prevRange(count, start, end): 取上N个有效时间段 var cron = '1 * * * * *'; var s = later.parse.cron(cron); var occurrences = later.schedule(s).next(100); // occurrences = later.schedule(demo2_b).next(3); for(var i = 0; i < occurrences.length; i++) { var now = new Date(occurrences[i]); var d = dateFormat(now, "yyyy:mm:dd h:MM:ss TT"); console.log(d); }
'date': req.body.str }; var selet = 'saying url'; Newz.findOne(query, selet, function (err, data) { if (err) { return console.error(err); } console.log(data); res.json(data); }); }); //UTC minus 4 equals to new york time later.date.UTC(); var sched = later.parse.recur().on('03:50:00').time(); var next = later.schedule(sched).next(10); console.log(next); later.setInterval(function () { action(); }, sched); //action(); function action() { var ran = Math.random(); if (ran < 0.4) { getNews(function (data) { var title = data.title; var url = data.url;
},function(err, reservaciones) { if (err) throw err; var excepciones = []; if(reservaciones.length > 0 ) { reservaciones.forEach(function(reserva) { excepciones.push(reserva.inicio); }); var excepcion_estado = 'DISPONIBILIDAD MEDIA'; } // Calculos basados en el horario de la empresa // TODO: agregar minutos al calculo, solo hora por ahora var horario_i= servicio.empresa().horario[0].split(":"); var horario_f=servicio.empresa().horario[1].split(":"); var hr_inicio = horario_i[0]; var hr_fin = horario_f[0]; var current = new Date(); var current_hour = current.getHours(); if ( is_target ) { var slots_hr= parseInt(hr_fin) - parseInt(hr_inicio) var slots_avail = (slots_hr * 60) / parseInt(servicio.duracion); } else { var slots_hr= parseInt(hr_fin) - parseInt(current_hour) var slots_avail = (slots_hr * 60) / parseInt(servicio.duracion); } // TODO: invalidar pedidos de fechas anteriores al dia de hoy - ya lo realiza empresa.status() if ( !is_target && current_hour >= parseInt(hr_inicio) && current_hour <= parseInt(hr_fin) ) { // horario actual valido, mostrar reservaciones del dia siguiente if (slots_hr <= 1 ){ var f_inicio = fin.setHours(parseInt(hr_inicio),0,0); var f_fin = fin.setHours(parseInt(hr_fin),0,0); var slot_start= new Date(f_inicio); var slot_end= new Date(f_fin); var estado = 'POR CERRAR'; slots_hr= parseInt(hr_fin) - parseInt(hr_inicio) slots_avail = (slots_hr * 60) / parseInt(servicio.duracion); } else { //TODO: Validate when target day var f_inicio = new Date(); var f_fin = current.setHours(parseInt(hr_fin),0,0); var slot_start= new Date(f_inicio.setHours(f_inicio.getHours()+1,0,0)); var slot_end= new Date(f_fin); var estado = 'DISPONIBLE'; } } else if ( !is_target && current_hour >= parseInt(hr_fin)) { // despues de cerrado muestra el dia siguiente var f_inicio = fin.setHours(parseInt(hr_inicio),0,0); var f_fin = fin.setHours(parseInt(hr_fin),0,0); var slot_start= new Date(f_inicio); var slot_end= new Date(f_fin); var estado = 'CERRADOS MOSTRANDO DIA SIGUIENTE'; } else { // el resto var f_inicio = target.setHours(parseInt(hr_inicio),0,0); var f_fin = target.setHours(parseInt(hr_fin)+1,0,0); var slot_start= new Date(f_inicio); var slot_end= new Date(f_fin); var estado = 'MOSTRANDO OTRO DIA'; } console.log('fecha:' + target + ' horarios empresa:' + hr_inicio + '-' + hr_fin); console.log('SLOTS:' + slot_start+ '-' + slot_end); if (excepciones.length > 0 ) { estado = excepcion_estado; } // if it is an hour if (parseInt(servicio.duracion) == 60) { var text = 'every 1 hour'; var sched = later.parse.text(text); console.log('schedule text:' + text); // if less than hour } else if (parseInt(servicio.duracion) < 60){ var text = 'every '+ servicio.duracion +' mins'; console.log('schedule text:' + text); var sched = later.parse.recur().every(parseInt(servicio.duracion)).minute(); } else { var text = 'every '+ servicio.duracion +' mins'; var sched = later.parse.recur().every(parseInt(servicio.duracion)).minute(); } console.log('excepciones generadas:', excepciones); var free_slots = later.schedule(sched).next(slots_avail, slot_start, slot_end); // console.log('Calculated slots:', free_slots); var remove_slots = free_slots; var remove_reservations= []; var result_slots = []; excepciones.forEach(function(ex) { i = 0; for (; i < remove_slots.length; i++){ if ( Date.parse(ex) === Date.parse(remove_slots[i]) ) { remove_reservations.push(i); } } }); len = remove_slots.length; for(var s= 0; s < len ; s++) { if ( remove_reservations.indexOf(s) > -1 ) { console.log('found match', s); } else { result_slots.push(remove_slots[s]); } } var result = [ { 'estado': estado, 'servicio': servicio, 'fecha': current, 'mostrando': slot_start }, { 'slots': result_slots} ]; cb(null, result); });