cron-parser
Advanced tools
Comparing version 1.1.1 to 2.0.0
@@ -5,3 +5,3 @@ { | ||
"description": "Node.js library for parsing crontab instructions", | ||
"version": "1.1.1", | ||
"version": "2.0.0", | ||
"keywords": ["cron", "crontab", "parser"], | ||
@@ -11,3 +11,3 @@ "dependencies": {}, | ||
"main": "lib/parser.js", | ||
"scripts": [ "lib/parser.js", "lib/expression.js", "lib/date.js" ] | ||
"scripts": [ "lib/parser.js", "lib/expression.js", "lib/date.js", "lib/number.js" ] | ||
} |
180
lib/date.js
'use strict'; | ||
/** | ||
* Date class extension methods | ||
*/ | ||
var extensions = { | ||
addYear: function addYear() { | ||
this.setFullYear(this.getFullYear() + 1); | ||
}, | ||
var moment = require('moment-timezone'); | ||
addMonth: function addMonth() { | ||
this.setDate(1); | ||
this.setHours(0); | ||
this.setMinutes(0); | ||
this.setSeconds(0); | ||
this.setMonth(this.getMonth() + 1); | ||
}, | ||
CronDate.prototype.addYear = function() { | ||
this._date.add(1, 'year'); | ||
}; | ||
addDay: function addDay() { | ||
var day = this.getDate(); | ||
this.setDate(day + 1); | ||
CronDate.prototype.addMonth = function() { | ||
this._date.add(1, 'month').startOf('month'); | ||
}; | ||
this.setHours(0); | ||
this.setMinutes(0); | ||
this.setSeconds(0); | ||
CronDate.prototype.addDay = function() { | ||
this._date.add(1, 'day').startOf('day'); | ||
}; | ||
if (this.getDate() === day) { | ||
this.setDate(day + 2); | ||
} | ||
}, | ||
CronDate.prototype.addHour = function() { | ||
this._date.add(1, 'hour').startOf('hour'); | ||
}; | ||
addHour: function addHour() { | ||
var hours = this.getHours(); | ||
this.setHours(hours + 1); | ||
CronDate.prototype.addMinute = function() { | ||
this._date.add(1, 'minute').startOf('minute'); | ||
}; | ||
if (this.getHours() === hours) { | ||
this.setHours(hours + 2); | ||
} | ||
CronDate.prototype.addSecond = function() { | ||
this._date.add(1, 'second').startOf('second'); | ||
}; | ||
this.setMinutes(0); | ||
this.setSeconds(0); | ||
}, | ||
CronDate.prototype.getDate = function() { | ||
return this._date.date(); | ||
}; | ||
addMinute: function addMinute() { | ||
this.setMinutes(this.getMinutes() + 1); | ||
this.setSeconds(0); | ||
}, | ||
CronDate.prototype.getFullYear = function() { | ||
return this._date.year(); | ||
}; | ||
addSecond: function addSecond() { | ||
this.setSeconds(this.getSeconds() + 1); | ||
}, | ||
CronDate.prototype.getDay = function() { | ||
return this._date.day(); | ||
}; | ||
toUTC: function toUTC() { | ||
var to = new CronDate(this); | ||
var ms = to.getTime() + (to.getTimezoneOffset() * 60000); | ||
to.setTime(ms); | ||
return to; | ||
} | ||
CronDate.prototype.getMonth = function() { | ||
return this._date.month(); | ||
}; | ||
/** | ||
* Extends Javascript Date class by adding | ||
* utility methods for basic date incrementation | ||
*/ | ||
CronDate.prototype.getHours = function() { | ||
return this._date.hours(); | ||
}; | ||
function CronDate (timestamp) { | ||
var date = timestamp ? new Date(timestamp) : new Date(); | ||
CronDate.prototype.getMinutes = function() { | ||
return this._date.minute(); | ||
}; | ||
// Attach extensions | ||
var methods = Object.keys(extensions); | ||
for (var i = 0, c = methods.length; i < c; i++) { | ||
var method = methods[i]; | ||
date[method] = extensions[method].bind(date); | ||
CronDate.prototype.getSeconds = function() { | ||
return this._date.second(); | ||
}; | ||
CronDate.prototype.getTime = function() { | ||
return this._date.valueOf(); | ||
}; | ||
CronDate.prototype.getUTCDate = function() { | ||
return this._getUTC().date(); | ||
}; | ||
CronDate.prototype.getUTCFullYear = function() { | ||
return this._getUTC().year(); | ||
}; | ||
CronDate.prototype.getUTCDay = function() { | ||
return this._getUTC().day(); | ||
}; | ||
CronDate.prototype.getUTCMonth = function() { | ||
return this._getUTC().month(); | ||
}; | ||
CronDate.prototype.getUTCHours = function() { | ||
return this._getUTC().hours(); | ||
}; | ||
CronDate.prototype.getUTCMinutes = function() { | ||
return this._getUTC().minute(); | ||
}; | ||
CronDate.prototype.getUTCSeconds = function() { | ||
return this._getUTC().second(); | ||
}; | ||
CronDate.prototype.setDate = function(d) { | ||
return this._date.date(d); | ||
}; | ||
CronDate.prototype.setFullYear = function(y) { | ||
return this._date.year(y); | ||
}; | ||
CronDate.prototype.setDay = function(d) { | ||
return this._date.day(d); | ||
}; | ||
CronDate.prototype.setMonth = function(m) { | ||
return this._date.month(m); | ||
}; | ||
CronDate.prototype.setHours = function(h) { | ||
return this._date.hour(h); | ||
}; | ||
CronDate.prototype.setMinutes = function(m) { | ||
return this._date.minute(m); | ||
}; | ||
CronDate.prototype.setSeconds = function(s) { | ||
return this._date.second(s); | ||
}; | ||
CronDate.prototype.getTime = function() { | ||
return this._date.valueOf(); | ||
}; | ||
CronDate.prototype._getUTC = function() { | ||
return moment.utc(this._date); | ||
}; | ||
CronDate.prototype.toString = function() { | ||
return this._date.toString(); | ||
}; | ||
function CronDate (timestamp, tz) { | ||
if (timestamp instanceof CronDate) { | ||
timestamp = timestamp._date; | ||
} | ||
return date; | ||
if (!tz) { | ||
this._date = moment(timestamp); | ||
} else { | ||
this._date = moment.tz(timestamp, tz); | ||
} | ||
} | ||
module.exports = CronDate; | ||
module.exports = CronDate; |
@@ -23,4 +23,5 @@ 'use strict'; | ||
this._options = options; | ||
this._currentDate = new CronDate(options.currentDate); | ||
this._endDate = options.endDate ? new CronDate(options.endDate) : null; | ||
this._tz = options.tz; | ||
this._currentDate = new CronDate(options.currentDate, this._tz); | ||
this._endDate = options.endDate ? new CronDate(options.endDate, this._tz) : null; | ||
this._fields = {}; | ||
@@ -311,2 +312,25 @@ this._isIterator = options.iterator || false; | ||
CronExpression.prototype._applyTimezoneShift = function(currentDate, method) { | ||
var previousHour = currentDate.getHours(); | ||
currentDate[method](); | ||
var currentHour = currentDate.getHours(); | ||
var diff = currentHour - previousHour; | ||
if (diff === 2) { | ||
// Starting DST | ||
if (this._fields.hour.length !== 24) { | ||
// Hour is specified | ||
this._dstStart = currentHour; | ||
} | ||
} else if ((diff === 0) && | ||
(currentDate.getMinutes() === 0) && | ||
(currentDate.getSeconds() === 0)) { | ||
// Ending DST | ||
if (this._fields.hour.length !== 24) { | ||
// Hour is specified | ||
this._dstEnd = currentHour; | ||
} | ||
} | ||
} | ||
/** | ||
@@ -319,2 +343,3 @@ * Find next matching schedule date | ||
CronExpression.prototype._findSchedule = function _findSchedule () { | ||
/** | ||
@@ -356,3 +381,3 @@ * Match field value | ||
} | ||
var method = function(name) { | ||
@@ -362,3 +387,3 @@ return !this._utc ? name : ('getUTC' + name.slice(3)); | ||
var currentDate = new CronDate(this._currentDate); | ||
var currentDate = new CronDate(this._currentDate, this._tz); | ||
var endDate = this._endDate; | ||
@@ -397,2 +422,4 @@ | ||
var currentHour = currentDate[method('getHours')](); | ||
// Validate days in month if explicit value is given | ||
@@ -453,10 +480,18 @@ if (!isMonthWildcardMatch) { | ||
// Match hour | ||
if (!matchSchedule(currentDate[method('getHours')](), this._fields.hour)) { | ||
currentDate.addHour(); | ||
if (!matchSchedule(currentHour, this._fields.hour)) { | ||
if (this._dstStart !== currentHour) { | ||
this._dstStart = null; | ||
this._applyTimezoneShift(currentDate, 'addHour'); | ||
continue; | ||
} | ||
} else if (this._dstEnd === currentHour) { | ||
this._dstEnd = null; | ||
this._applyTimezoneShift(currentDate, 'addHour'); | ||
continue; | ||
} | ||
// Match minute | ||
if (!matchSchedule(currentDate[method('getMinutes')](), this._fields.minute)) { | ||
currentDate.addMinute(); | ||
this._applyTimezoneShift(currentDate, 'addMinute'); | ||
continue; | ||
@@ -467,3 +502,3 @@ } | ||
if (!matchSchedule(currentDate[method('getSeconds')](), this._fields.second)) { | ||
currentDate.addSecond(); | ||
this._applyTimezoneShift(currentDate, 'addSecond'); | ||
continue; | ||
@@ -476,3 +511,3 @@ } | ||
// When internal date is not mutated, append one second as a padding | ||
var nextDate = new CronDate(currentDate); | ||
var nextDate = new CronDate(currentDate, this._tz); | ||
if (this._currentDate !== currentDate) { | ||
@@ -573,2 +608,3 @@ nextDate.addSecond(); | ||
CronExpression.parse = function parse (expression, options, callback) { | ||
var self = this; | ||
if (typeof options === 'function') { | ||
@@ -585,3 +621,3 @@ callback = options; | ||
if (!options.currentDate) { | ||
options.currentDate = new CronDate(); | ||
options.currentDate = new CronDate(undefined, self._tz); | ||
} | ||
@@ -588,0 +624,0 @@ |
{ | ||
"name": "cron-parser", | ||
"version": "1.1.1", | ||
"version": "2.0.0", | ||
"description": "Node.js library for parsing crontab instructions", | ||
@@ -36,2 +36,5 @@ "main": "lib/parser.js", | ||
"license": "MIT", | ||
"dependencies": { | ||
"moment-timezone": "^0.5.0" | ||
}, | ||
"devDependencies": { | ||
@@ -38,0 +41,0 @@ "tap": "^0.5.0" |
@@ -7,3 +7,3 @@ cron-parser | ||
Node.js library for parsing crontab instructions | ||
Node.js library for parsing crontab instructions. It includes support for timezones and DST transitions. | ||
@@ -88,2 +88,23 @@ Setup | ||
Timezone support | ||
```javascript | ||
var parser = require('cron-parser'); | ||
var options = { | ||
currentDate: '2016-03-27 00:00:01', | ||
tz: 'Europe/Athens' | ||
}; | ||
try { | ||
var interval = CronExpression.parse('0 * * * *', options); | ||
console.log('Date: ', interval.next().toString()); // Date: Sun Mar 27 2016 01:00:00 GMT+0200 | ||
console.log('Date: ', interval.next().toString()); // Date: Sun Mar 27 2016 02:00:00 GMT+0200 | ||
console.log('Date: ', interval.next().toString()); // Date: Sun Mar 27 2016 04:00:00 GMT+0300 (Notice DST transition) | ||
} catch (err) { | ||
console.log('Error: ' + err.message); | ||
} | ||
``` | ||
Options | ||
@@ -94,3 +115,16 @@ ======== | ||
* *endDate* - End date of the iteration | ||
`currentDate` and `endDate` accept `string`, `integer` and `Date` as input. | ||
In case of using `string` as input, not every string format accepted | ||
by the `Date` constructor will work correctly. The supported formats are: [`ISO8601`](http://momentjs.com/docs/#/parsing/string/) and the older | ||
[`ASP.NET JSON Date`](http://momentjs.com/docs/#/parsing/asp-net-json-date/) format. The reason being that those are the formats accepted by the | ||
[`moment`](http://momentjs.com) library which is being used to handle dates. | ||
Using `Date` as an input can be problematic specially when using the `tz` option. The issue being that, when creating a new `Date` object without | ||
any timezone information, it will be created in the timezone of the system that is running the code. This (most of times) won't be what the user | ||
will be expecting. Using one of the supported `string` formats will solve the issue(see timezone example). | ||
* *iterator* - Return ES6 compatible iterator object | ||
* *utc* - Enable UTC | ||
* *tz* - Timezone string |
@@ -9,4 +9,5 @@ var util = require('util'); | ||
var i; | ||
for (i = 0; i < 100; ++i) { | ||
interval.next(); | ||
var d; | ||
for (i = 0; i < 20; ++i) { | ||
d = interval.next(); | ||
} | ||
@@ -13,0 +14,0 @@ t.end(); |
Sorry, the diff of this file is not supported yet
116514
23
1624
128
1
+ Addedmoment-timezone@^0.5.0
+ Addedmoment@2.30.1(transitive)
+ Addedmoment-timezone@0.5.47(transitive)