croner 4.0.53 → 4.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/FUNDING.yml +1 -0
- package/README.md +138 -105
- package/dist/croner.min.js +1 -1
- package/dist/croner.min.mjs +1 -1
- package/dist-legacy/croner.cjs +1 -1
- package/package.json +1 -1
- package/src/croner.js +11 -11
- package/src/date.js +54 -15
- package/src/pattern.js +149 -73
- package/test/src/suite.cjs +25 -34
- package/types/croner.d.ts +6 -4
- package/types/date.d.ts +7 -5
- package/types/pattern.d.ts +8 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
github: [hexagon]
|
package/README.md
CHANGED
|
@@ -4,35 +4,45 @@
|
|
|
4
4
|
[](https://github.com/Hexagon/croner/blob/master/LICENSE) [](https://www.jsdelivr.com/package/npm/croner)
|
|
5
5
|
|
|
6
6
|
* Trigger functions in javascript using [Cron](https://en.wikipedia.org/wiki/Cron#CRON_expression) syntax.
|
|
7
|
-
* Pause, resume or stop
|
|
7
|
+
* Pause, resume or stop execution efter a task is scheduled.
|
|
8
8
|
* Find first date of next month, find date of next tuesday, etc.
|
|
9
9
|
* Supports Node.js from 4.0 to current. Both require (commonjs) and import (module).
|
|
10
10
|
* 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))
|
|
11
|
-
*
|
|
11
|
+
* **Experimental:** Schedule in other timezones than default.
|
|
12
12
|
|
|
13
13
|
Documented with [JSDoc](https://jsdoc.app/) for intellisense, and include [TypeScript](https://www.typescriptlang.org/) typings.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
<script src="https://cdn.jsdelivr.net/npm/croner@4/dist/croner.min.js"></script>
|
|
17
|
-
```
|
|
15
|
+
Quick demo:
|
|
18
16
|
|
|
19
17
|
```javascript
|
|
20
|
-
// Run a function
|
|
21
|
-
Cron('* * * * * *',
|
|
18
|
+
// Run a function at the interval set by a cron expression
|
|
19
|
+
let job = Cron('* * * * * *', () => {
|
|
22
20
|
console.log('This will run every second');
|
|
23
21
|
});
|
|
24
22
|
|
|
25
|
-
//
|
|
26
|
-
|
|
23
|
+
// Control execution
|
|
24
|
+
// job.pause();
|
|
25
|
+
// job.resume();
|
|
26
|
+
// job.stop();
|
|
27
|
+
|
|
28
|
+
// Get info
|
|
29
|
+
let next = job.next();
|
|
30
|
+
let previous = job.previous();
|
|
27
31
|
```
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
```javascript
|
|
34
|
+
// What date is next sunday?
|
|
35
|
+
let nextSunday = Cron('0 0 0 * * 7').next();
|
|
36
|
+
console.log(nextSunday.toLocaleDateString());
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
// How many days left to christmas eve?
|
|
39
|
+
let msLeft = Cron('59 59 23 24 DEC *').next() - new Date();
|
|
40
|
+
console.log(Math.floor(msLeft/1000/3600/24) + " days left to next christmas eve");
|
|
41
|
+
```
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
More [examples](#examples)...
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
36
46
|
|
|
37
47
|
### Node.js
|
|
38
48
|
|
|
@@ -49,7 +59,15 @@ import Cron from "croner";
|
|
|
49
59
|
const Cron = require("croner");
|
|
50
60
|
```
|
|
51
61
|
|
|
52
|
-
###
|
|
62
|
+
### Browser
|
|
63
|
+
|
|
64
|
+
#### Manual
|
|
65
|
+
|
|
66
|
+
* Download latest [zipball](http://github.com/Hexagon/croner/zipball/master/)
|
|
67
|
+
* Unpack
|
|
68
|
+
* 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
|
|
69
|
+
|
|
70
|
+
#### CDN
|
|
53
71
|
|
|
54
72
|
To use as a [UMD](https://github.com/umdjs/umd)-module (stand alone, [RequireJS](https://requirejs.org/) etc.)
|
|
55
73
|
|
|
@@ -83,133 +101,148 @@ To use as a [ES-module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/
|
|
|
83
101
|
</script>
|
|
84
102
|
```
|
|
85
103
|
|
|
86
|
-
##
|
|
104
|
+
## Signature
|
|
87
105
|
|
|
88
|
-
|
|
89
|
-
```javascript
|
|
90
|
-
// Run a function each second
|
|
91
|
-
Cron('* * * * * *', function () {
|
|
92
|
-
console.log('This will run every second');
|
|
93
|
-
});
|
|
94
|
-
```
|
|
106
|
+
Cron takes three arguments; [pattern](#pattern), [options](#options) (optional) and a scheduled function (optional).
|
|
95
107
|
|
|
96
|
-
### Find dates
|
|
97
108
|
```javascript
|
|
98
|
-
// Find next month
|
|
99
|
-
let nextMonth = Cron('0 0 0 1 * *').next(),
|
|
100
|
-
nextSunday = Cron('0 0 0 * * 7').next();
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
console.log("Next sunday: " + nextSunday.toLocaleDateString());
|
|
104
|
-
```
|
|
110
|
+
var scheduler = Cron( <string pattern> [, { ... } ] [, <function toBeRun> ] );
|
|
105
111
|
|
|
106
|
-
### Minimalist scheduling with stepping and custom timezone
|
|
107
|
-
```javascript
|
|
108
|
-
// Run a function every fifth second
|
|
109
|
-
Cron('*/5 * * * * *', { timezone: 'Europe/Stockholm' }, function () {
|
|
110
|
-
console.log('This will run every fifth second');
|
|
111
|
-
});
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
```javascript
|
|
116
|
-
// Run a function the first five seconds of a minute
|
|
117
|
-
Cron('0-4 * * * * *', function () {
|
|
118
|
-
console.log('This will run the first five seconds every minute');
|
|
119
|
-
});
|
|
120
|
-
```
|
|
114
|
+
Cron return a scheduler, which can be used in a couple of different ways.
|
|
121
115
|
|
|
122
|
-
### Minimalist scheduling with options
|
|
123
116
|
```javascript
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
job.next( [ <date previous> ] ); // Get a Date object with next run time according
|
|
118
|
+
// to pattern relative to previous, or now if omitted
|
|
119
|
+
|
|
120
|
+
job.msToNext( [ <date previous> ] ); // Get milliseconds left to next execution
|
|
121
|
+
|
|
122
|
+
job.previous(); // Gets a Date object with previous run time, or null
|
|
123
|
+
|
|
124
|
+
job.schedule( <fn job> ); // If you didn't pass a function to constructor, you can do it here
|
|
125
|
+
|
|
126
|
+
job.pause(); // Pause execution
|
|
127
|
+
job.resume(); // Resume execution
|
|
128
|
+
job.stop(); // Stop execution
|
|
128
129
|
```
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
## Options
|
|
132
|
+
|
|
133
|
+
Options are optional, and passed as the second parameter of cron.
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
|
|
131
137
|
```javascript
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
console.log('This will run each second.');
|
|
135
|
-
});
|
|
138
|
+
Cron( '* * * * * *', { maxRuns: 4 } );
|
|
139
|
+
```
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
| Key | Default value | Data type | Remarks |
|
|
142
|
+
|--------------|----------------|----------------|---------------------------------------|
|
|
143
|
+
| maxRuns | Infinite | Number | |
|
|
144
|
+
| timezone | undefined | String | Timezone in Europe/Stockholm format |
|
|
145
|
+
| startAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local or specified timezone |
|
|
146
|
+
| stopAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local or specified timezone |
|
|
147
|
+
| paused | false | Boolean | If the job should be paused from start. |
|
|
139
148
|
|
|
140
|
-
|
|
141
|
-
job.resume();
|
|
149
|
+
## Pattern
|
|
142
150
|
|
|
143
|
-
|
|
144
|
-
job.stop();
|
|
151
|
+
Pattern is mandatory, and passed as the first argument of Cron.
|
|
145
152
|
|
|
146
|
-
|
|
153
|
+
Example:
|
|
147
154
|
|
|
148
|
-
### Basic scheduling
|
|
149
155
|
```javascript
|
|
156
|
+
Cron( '* * * * * *', () => {} );
|
|
157
|
+
```
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
var scheduler = Cron('0 * * * * *');
|
|
159
|
+
Composition:
|
|
153
160
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
161
|
+
```
|
|
162
|
+
┌──────────────── (optional) second (0 - 59)
|
|
163
|
+
│ ┌────────────── minute (0 - 59)
|
|
164
|
+
│ │ ┌──────────── hour (0 - 23)
|
|
165
|
+
│ │ │ ┌────────── day of month (1 - 31)
|
|
166
|
+
│ │ │ │ ┌──────── month (1 - 12, JAN-DEC)
|
|
167
|
+
│ │ │ │ │ ┌────── day of week (0 - 6, SUN-Mon)
|
|
168
|
+
│ │ │ │ │ │ (0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0)
|
|
169
|
+
│ │ │ │ │ │
|
|
170
|
+
* * * * * *
|
|
157
171
|
```
|
|
158
172
|
|
|
159
|
-
|
|
160
|
-
|
|
173
|
+
Details:
|
|
174
|
+
|
|
175
|
+
| Field | Required | Allowed values | Allowed special characters | Remarks |
|
|
176
|
+
|--------------|----------|----------------|----------------------------|---------------------------------------|
|
|
177
|
+
| Seconds | Optional | 0-59 | * , - / | |
|
|
178
|
+
| Minutes | Yes | 0-59 | * , - / | |
|
|
179
|
+
| Hours | Yes | 0-23 | * , - / | |
|
|
180
|
+
| Day of Month | Yes | 1-31 | * , - / | |
|
|
181
|
+
| Month | Yes | 1-12 or JAN-DEC| * , - / | |
|
|
182
|
+
| Day of Week | Yes | 0-7 or SUN-MON | * , - / | 0 to 6 are Sunday to Saturday<br>7 is Sunday, the same as 0 |
|
|
161
183
|
|
|
162
|
-
|
|
163
|
-
var scheduler = Cron('0 * * * * *', { maxRuns: 5 });
|
|
184
|
+
**Note**: Weekday and month names are case insensitive. Both MON and mon works.
|
|
164
185
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
186
|
+
## Examples
|
|
187
|
+
|
|
188
|
+
### Minimal
|
|
189
|
+
```javascript
|
|
190
|
+
// Run a function each second
|
|
191
|
+
Cron('* * * * * *', () => {
|
|
192
|
+
console.log('This will run every second');
|
|
168
193
|
});
|
|
169
194
|
```
|
|
170
|
-
### Scheduling with controls
|
|
171
|
-
```javascript
|
|
172
|
-
let scheduler = Cron('* * * * * *')
|
|
173
195
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
console.log('
|
|
196
|
+
### Expressions
|
|
197
|
+
```javascript
|
|
198
|
+
// Run a function the first five seconds of a minute
|
|
199
|
+
Cron('0-4 */5 1,2,3 * JAN-MAR SAT', function () {
|
|
200
|
+
console.log('This will run the first five seconds every fifth minute');
|
|
201
|
+
console.log('of hour 1,2 and 3 every saturday in January to March.');
|
|
179
202
|
});
|
|
180
|
-
|
|
181
|
-
Cron('10 * * * * *', {maxRuns: 1}, () => scheduler.pause());
|
|
182
|
-
Cron('15 * * * * *', {maxRuns: 1}, () => scheduler.resume());
|
|
183
|
-
Cron('20 * * * * *', {maxRuns: 1}, () => scheduler.stop());
|
|
184
203
|
```
|
|
185
204
|
|
|
186
|
-
|
|
205
|
+
### Find dates
|
|
187
206
|
```javascript
|
|
207
|
+
// Find next month
|
|
208
|
+
let nextMonth = Cron('0 0 0 1 * *').next(),
|
|
209
|
+
nextSunday = Cron('0 0 0 * * 7').next(),
|
|
210
|
+
nextSat29feb = Cron("0 0 0 29 2 6").next();
|
|
188
211
|
|
|
189
|
-
|
|
212
|
+
console.log("First day of next month: " + nextMonth.toLocaleDateString());
|
|
213
|
+
console.log("Next sunday: " + nextSunday.toLocaleDateString());
|
|
214
|
+
console.log("Next saturday at 29th of february: " + nextSat29feb.toLocaleDateString()); // 2048-02-29
|
|
215
|
+
```
|
|
190
216
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
scheduler.previous();
|
|
194
|
-
scheduler.schedule( <fn job> );
|
|
195
|
-
scheduler.pause();
|
|
196
|
-
scheduler.resume();
|
|
197
|
-
scheduler.stop();
|
|
217
|
+
### With options
|
|
218
|
+
```javascript
|
|
198
219
|
|
|
220
|
+
var job = Cron(
|
|
221
|
+
'* * * * *',
|
|
222
|
+
{
|
|
223
|
+
maxRuns: Infinity,
|
|
224
|
+
startAt: "2021-11-01T00:00:00",
|
|
225
|
+
stopAt: "2021-12-01T00:00:00",
|
|
226
|
+
timezone: "Europe/Stockholm"
|
|
227
|
+
},
|
|
228
|
+
function() {
|
|
229
|
+
console.log('This will run every minute, from 2021-11-01 to 2021-12-01 00:00:00 in Europe/Stockholm.');
|
|
230
|
+
}
|
|
231
|
+
);
|
|
199
232
|
```
|
|
200
233
|
|
|
201
|
-
|
|
234
|
+
### Job controls
|
|
235
|
+
```javascript
|
|
236
|
+
let job = Cron('* * * * * *', () => {
|
|
237
|
+
console.log('This will run every second. Pause on second 10. Resume on second 15. And quit on second 20.');
|
|
238
|
+
console.log('Current second: ', new Date().getSeconds());
|
|
239
|
+
console.log('Previous run: ' + job.previous());
|
|
240
|
+
console.log('Next run: ' + job.next());
|
|
241
|
+
});
|
|
202
242
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
│ │ ┌──────────── hour (0 - 23)
|
|
207
|
-
│ │ │ ┌────────── day of month (1 - 31)
|
|
208
|
-
│ │ │ │ ┌──────── month (1 - 12)
|
|
209
|
-
│ │ │ │ │ ┌────── day of week (0 - 6)
|
|
210
|
-
│ │ │ │ │ │ (0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0)
|
|
211
|
-
│ │ │ │ │ │
|
|
212
|
-
* * * * * *
|
|
243
|
+
Cron('10 * * * * *', {maxRuns: 1}, () => job.pause());
|
|
244
|
+
Cron('15 * * * * *', {maxRuns: 1}, () => job.resume());
|
|
245
|
+
Cron('20 * * * * *', {maxRuns: 1}, () => job.stop());
|
|
213
246
|
```
|
|
214
247
|
|
|
215
248
|
## License
|
package/dist/croner.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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
|
|
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 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:()=>o});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,e){if(this.timezone){let r=t.getTime(),n=function(t,e){return new Date(t.toLocaleString("en-US",{timeZone:e}))}(t,this.timezone);e||(t=n),this.UTCmsOffset=n.getTime()-r}else this.UTCmsOffset=0;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=this.parseISOLocal(t);if(isNaN(e))throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");this.fromDate(new Date(e),!0)},r.prototype.increment=function(t,e){e||(this.seconds+=1);let n=this.getTime();this.milliseconds=0;let i=this,s=function(t,e,r,n){for(let s=void 0===n?i[t]+r:0+r;s<e[t].length;s++)if(e[t][s])return i[t]=s-r,!0;return!1},o=function(){for(;p>=0;)s(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;)s(a[p][0],t,a[p][2])||(this[a[p][1]]++,o()),p++;for(;!t.daysOfWeek[this.getDate(!0).getDay()];)this.days+=1,p=2,o();return n!=i.getTime()?(i=new r(i),this.years>=4e3?null:i.increment(t,!0)):this},r.prototype.getDate=function(t){let e=t?0:this.UTCmsOffset;return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-e)},r.prototype.getTime=function(t){let e=t?0:this.UTCmsOffset;return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-e).getTime()},r.prototype.parseISOLocal=function(t){let e=t.split(/\D/);if(e.length<6)return NaN;let r=parseInt(e[0],10),n=parseInt(e[1],10),i=parseInt(e[2],10),s=parseInt(e[3],10),o=parseInt(e[4],10),a=parseInt(e[5],10);return isNaN(r)||isNaN(n)||isNaN(i)||isNaN(s)||isNaN(o)||isNaN(a)?NaN:new Date(r,n-1,i,s,o,a)},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,i,s=this[t];if("*"!==e)if(i=e.split(","),i.length>1)for(n=0;n<i.length;n++)this.partToArray(t,i[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<s.length;n++)s[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 i=parseInt(n[0],10)+r,s=parseInt(n[1],10)+r;if(isNaN(i))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(s))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(i<0||s>=this[e].length)throw new TypeError("CronPattern: Value out of range: '"+t+"'");if(i>s)throw new TypeError("CronPattern: From value is larger than to value: '"+t+"'");for(let t=i;t<=s;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 i=parseInt(n[1],10);if(isNaN(i))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(0===i)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(i>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+=i)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 i=Math.pow(2,31)-1;function s(t,e,r){return this instanceof s?(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 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){t=new r(t,this.options.timezone);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){this.options.startAt&&t&&t.getTime(!0)<this.options.startAt.getTime(!0)&&(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(!0)>=this.options.stopAt.getTime(!0)?null:e},s.prototype.msToNext=function(t){t=new r(t,this.options.timezone);let e=this._next(t);return e?e.getTime(!0)-t.getTime(!0):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,n=this.msToNext(e.previousrun),s=e.maxDelay||i;return n>s&&(n=s),null!==n&&(e.currentTimeout=setTimeout((function(){n!==s&&(e.options.paused||(e.options.maxRuns--,t()),e.previousrun=new r(void 0,e.options.timezone)),e.schedule(t)}),n)),this};const o=s;return e.default})()}));
|
package/dist/croner.min.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t={d:(e,r)=>{for(var
|
|
1
|
+
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,{P:()=>i,Z:()=>o});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,e){if(this.timezone){let r=t.getTime(),n=function(t,e){return new Date(t.toLocaleString("en-US",{timeZone:e}))}(t,this.timezone);e||(t=n),this.UTCmsOffset=n.getTime()-r}else this.UTCmsOffset=0;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=this.parseISOLocal(t);if(isNaN(e))throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");this.fromDate(new Date(e),!0)},r.prototype.increment=function(t,e){e||(this.seconds+=1);let n=this.getTime();this.milliseconds=0;let s=this,i=function(t,e,r,n){for(let i=void 0===n?s[t]+r:0+r;i<e[t].length;i++)if(e[t][i])return s[t]=i-r,!0;return!1},o=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]]++,o()),p++;for(;!t.daysOfWeek[this.getDate(!0).getDay()];)this.days+=1,p=2,o();return n!=s.getTime()?(s=new r(s),this.years>=4e3?null:s.increment(t,!0)):this},r.prototype.getDate=function(t){let e=t?0:this.UTCmsOffset;return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-e)},r.prototype.getTime=function(t){let e=t?0:this.UTCmsOffset;return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-e).getTime()},r.prototype.parseISOLocal=function(t){let e=t.split(/\D/);if(e.length<6)return NaN;let r=parseInt(e[0],10),n=parseInt(e[1],10),s=parseInt(e[2],10),i=parseInt(e[3],10),o=parseInt(e[4],10),a=parseInt(e[5],10);return isNaN(r)||isNaN(n)||isNaN(s)||isNaN(i)||isNaN(o)||isNaN(a)?NaN:new Date(r,n-1,s,i,o,a)},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,s,i=this[t];if("*"!==e)if(s=e.split(","),s.length>1)for(n=0;n<s.length;n++)this.partToArray(t,s[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 s=parseInt(n[0],10)+r,i=parseInt(n[1],10)+r;if(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>=this[e].length)throw new TypeError("CronPattern: Value out of range: '"+t+"'");if(s>i)throw new TypeError("CronPattern: From value is larger than to value: '"+t+"'");for(let t=s;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 s=parseInt(n[1],10);if(isNaN(s))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(0===s)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(s>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+=s)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 s=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){t=new r(t,this.options.timezone);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){this.options.startAt&&t&&t.getTime(!0)<this.options.startAt.getTime(!0)&&(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(!0)>=this.options.stopAt.getTime(!0)?null:e},i.prototype.msToNext=function(t){t=new r(t,this.options.timezone);let e=this._next(t);return e?e.getTime(!0)-t.getTime(!0):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||s;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 o=i;var a=e.P,p=e.Z;export{a as Cron,p as default};
|
package/dist-legacy/croner.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
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
|
|
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 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:()=>o});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,e){if(this.timezone){let r=t.getTime(),n=function(t,e){return new Date(t.toLocaleString("en-US",{timeZone:e}))}(t,this.timezone);e||(t=n),this.UTCmsOffset=n.getTime()-r}else this.UTCmsOffset=0;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=this.parseISOLocal(t);if(isNaN(e))throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");this.fromDate(new Date(e),!0)},r.prototype.increment=function(t,e){e||(this.seconds+=1);let n=this.getTime();this.milliseconds=0;let i=this,s=function(t,e,r,n){for(let s=void 0===n?i[t]+r:0+r;s<e[t].length;s++)if(e[t][s])return i[t]=s-r,!0;return!1},o=function(){for(;p>=0;)s(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;)s(a[p][0],t,a[p][2])||(this[a[p][1]]++,o()),p++;for(;!t.daysOfWeek[this.getDate(!0).getDay()];)this.days+=1,p=2,o();return n!=i.getTime()?(i=new r(i),this.years>=4e3?null:i.increment(t,!0)):this},r.prototype.getDate=function(t){let e=t?0:this.UTCmsOffset;return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-e)},r.prototype.getTime=function(t){let e=t?0:this.UTCmsOffset;return new Date(this.years,this.months,this.days,this.hours,this.minutes,this.seconds,this.milliseconds-e).getTime()},r.prototype.parseISOLocal=function(t){let e=t.split(/\D/);if(e.length<6)return NaN;let r=parseInt(e[0],10),n=parseInt(e[1],10),i=parseInt(e[2],10),s=parseInt(e[3],10),o=parseInt(e[4],10),a=parseInt(e[5],10);return isNaN(r)||isNaN(n)||isNaN(i)||isNaN(s)||isNaN(o)||isNaN(a)?NaN:new Date(r,n-1,i,s,o,a)},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,i,s=this[t];if("*"!==e)if(i=e.split(","),i.length>1)for(n=0;n<i.length;n++)this.partToArray(t,i[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<s.length;n++)s[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 i=parseInt(n[0],10)+r,s=parseInt(n[1],10)+r;if(isNaN(i))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(s))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(i<0||s>=this[e].length)throw new TypeError("CronPattern: Value out of range: '"+t+"'");if(i>s)throw new TypeError("CronPattern: From value is larger than to value: '"+t+"'");for(let t=i;t<=s;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 i=parseInt(n[1],10);if(isNaN(i))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(0===i)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(i>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+=i)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 i=Math.pow(2,31)-1;function s(t,e,r){return this instanceof s?(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 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){t=new r(t,this.options.timezone);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){this.options.startAt&&t&&t.getTime(!0)<this.options.startAt.getTime(!0)&&(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(!0)>=this.options.stopAt.getTime(!0)?null:e},s.prototype.msToNext=function(t){t=new r(t,this.options.timezone);let e=this._next(t);return e?e.getTime(!0)-t.getTime(!0):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,n=this.msToNext(e.previousrun),s=e.maxDelay||i;return n>s&&(n=s),null!==n&&(e.currentTimeout=setTimeout((function(){n!==s&&(e.options.paused||(e.options.maxRuns--,t()),e.previousrun=new r(void 0,e.options.timezone)),e.schedule(t)}),n)),this};const o=s;return e.default})()}));
|
package/package.json
CHANGED
package/src/croner.js
CHANGED
|
@@ -152,14 +152,16 @@ Cron.prototype.processOptions = function (options) {
|
|
|
152
152
|
* @returns {Date | null} - Next run time
|
|
153
153
|
*/
|
|
154
154
|
Cron.prototype.next = function (prev) {
|
|
155
|
+
prev = new CronDate(prev, this.options.timezone);
|
|
155
156
|
let next = this._next(prev);
|
|
156
157
|
return next ? next.getDate() : null;
|
|
157
158
|
};
|
|
158
159
|
|
|
159
160
|
/**
|
|
160
161
|
* Return previous run time
|
|
162
|
+
* @public
|
|
161
163
|
*
|
|
162
|
-
* @returns {
|
|
164
|
+
* @returns {CronDate | null} - Previous run time
|
|
163
165
|
*/
|
|
164
166
|
Cron.prototype.previous = function () {
|
|
165
167
|
return this.previousrun ? this.previousrun.getDate() : null;
|
|
@@ -169,26 +171,23 @@ Cron.prototype.previous = function () {
|
|
|
169
171
|
* Internal version of next. Cron needs millseconds internally, hence _next.
|
|
170
172
|
* @private
|
|
171
173
|
*
|
|
172
|
-
* @param {
|
|
174
|
+
* @param {CronDate} prev - Input pattern
|
|
173
175
|
* @returns {CronDate | null} - Next run time
|
|
174
176
|
*/
|
|
175
177
|
Cron.prototype._next = function (prev) {
|
|
176
178
|
|
|
177
|
-
prev = new CronDate(prev, this.options.timezone);
|
|
178
|
-
|
|
179
179
|
// Previous run should never be before startAt
|
|
180
|
-
if( this.options.startAt && prev && prev.getTime() < this.options.startAt.getTime() ) {
|
|
180
|
+
if( this.options.startAt && prev && prev.getTime(true) < this.options.startAt.getTime(true) ) {
|
|
181
181
|
prev = new CronDate(this.options.startAt, this.options.timezone);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
// Calculate next run
|
|
185
185
|
let nextRun = new CronDate(prev, this.options.timezone).increment(this.pattern);
|
|
186
186
|
|
|
187
|
-
// Check for stop condition
|
|
188
187
|
if ((nextRun === null) ||
|
|
189
188
|
(this.options.maxRuns <= 0) ||
|
|
190
189
|
(this.options.kill) ||
|
|
191
|
-
(this.options.stopAt && nextRun.getTime() >= this.options.stopAt.getTime() )) {
|
|
190
|
+
(this.options.stopAt && nextRun.getTime(true) >= this.options.stopAt.getTime(true) )) {
|
|
192
191
|
return null;
|
|
193
192
|
} else {
|
|
194
193
|
// All seem good, return next run
|
|
@@ -199,15 +198,16 @@ Cron.prototype._next = function (prev) {
|
|
|
199
198
|
|
|
200
199
|
/**
|
|
201
200
|
* Returns number of milliseconds to next run
|
|
201
|
+
* @public
|
|
202
202
|
*
|
|
203
203
|
* @param {CronNextResult} [prev=new CronDate()] - Starting date, defaults to now
|
|
204
204
|
* @returns {number | null}
|
|
205
205
|
*/
|
|
206
206
|
Cron.prototype.msToNext = function (prev) {
|
|
207
|
-
prev =
|
|
207
|
+
prev = new CronDate(prev, this.options.timezone);
|
|
208
208
|
let next = this._next(prev);
|
|
209
209
|
if( next ) {
|
|
210
|
-
return (next.getTime() - prev.getTime());
|
|
210
|
+
return (next.getTime(true) - prev.getTime(true));
|
|
211
211
|
} else {
|
|
212
212
|
return null;
|
|
213
213
|
}
|
|
@@ -226,7 +226,7 @@ Cron.prototype.stop = function () {
|
|
|
226
226
|
};
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
|
-
* Pause
|
|
229
|
+
* Pause executionR
|
|
230
230
|
* @public
|
|
231
231
|
*
|
|
232
232
|
* @returns {boolean} - Wether pause was successful
|
|
@@ -283,7 +283,7 @@ Cron.prototype.schedule = function (func) {
|
|
|
283
283
|
self.previousrun = new CronDate(void 0, self.options.timezone);
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
//
|
|
286
|
+
// Recurse
|
|
287
287
|
self.schedule(func);
|
|
288
288
|
|
|
289
289
|
}, waitMs );
|
package/src/date.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import convertTZ from "./timezone.js";
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* Converts date to CronDate
|
|
5
4
|
* @constructor
|
|
6
5
|
*
|
|
7
|
-
* @param {date|string} [date] - Input date
|
|
6
|
+
* @param {date|string} [date] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected
|
|
8
7
|
* @param {string} [timezone] - String representation of timezone in Europe/Stockholm format.
|
|
9
8
|
*/
|
|
10
9
|
function CronDate (date, timezone) {
|
|
@@ -29,17 +28,22 @@ function CronDate (date, timezone) {
|
|
|
29
28
|
* @private
|
|
30
29
|
*
|
|
31
30
|
* @param {date} date - Input date
|
|
31
|
+
* @param {boolean} [fromLocal] - Input date already in target timezone
|
|
32
32
|
*/
|
|
33
|
-
CronDate.prototype.fromDate = function (date) {
|
|
33
|
+
CronDate.prototype.fromDate = function (date, fromLocal) {
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
// This is the only way in for a pure date object, so this is where timezone should be applied
|
|
37
|
-
let originalUTCms = date.getTime();
|
|
38
37
|
if (this.timezone) {
|
|
39
|
-
|
|
38
|
+
let originalUTCms = date.getTime(),
|
|
39
|
+
convertedDate = convertTZ(date, this.timezone);
|
|
40
|
+
if (!fromLocal) {
|
|
41
|
+
date = convertedDate;
|
|
42
|
+
}
|
|
43
|
+
this.UTCmsOffset = convertedDate.getTime() - originalUTCms;
|
|
44
|
+
} else {
|
|
45
|
+
this.UTCmsOffset = 0;
|
|
40
46
|
}
|
|
41
|
-
let convertedUTCms = date.getTime();
|
|
42
|
-
this.UTCmsOffset = convertedUTCms - originalUTCms;
|
|
43
47
|
|
|
44
48
|
this.milliseconds = date.getMilliseconds();
|
|
45
49
|
this.seconds = date.getSeconds();
|
|
@@ -82,14 +86,14 @@ CronDate.prototype.fromCronDate = function (date) {
|
|
|
82
86
|
*/
|
|
83
87
|
CronDate.prototype.fromString = function (str) {
|
|
84
88
|
|
|
85
|
-
let parsedDateUTCms =
|
|
89
|
+
let parsedDateUTCms = this.parseISOLocal(str);
|
|
86
90
|
|
|
87
91
|
// Throw if we did get an invalid date
|
|
88
92
|
if( isNaN(parsedDateUTCms) ) {
|
|
89
93
|
throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
this.fromDate(new Date(parsedDateUTCms));
|
|
96
|
+
this.fromDate(new Date(parsedDateUTCms), true);
|
|
93
97
|
};
|
|
94
98
|
|
|
95
99
|
/**
|
|
@@ -194,7 +198,7 @@ CronDate.prototype.increment = function (pattern, rerun) {
|
|
|
194
198
|
|
|
195
199
|
// This is a special case for weekday, as the user isn't able to combine date/month patterns
|
|
196
200
|
// with weekday patterns, it's just to increment days until we get a match.
|
|
197
|
-
while (!pattern.daysOfWeek[this.getDate().getDay()]) {
|
|
201
|
+
while (!pattern.daysOfWeek[this.getDate(true).getDay()]) {
|
|
198
202
|
this.days += 1;
|
|
199
203
|
doing = 2;
|
|
200
204
|
resetPrevious();
|
|
@@ -219,22 +223,57 @@ CronDate.prototype.increment = function (pattern, rerun) {
|
|
|
219
223
|
* Convert current state back to a javascript Date()
|
|
220
224
|
* @public
|
|
221
225
|
*
|
|
226
|
+
* @param {boolean} internal - If this is an internal call
|
|
222
227
|
* @returns {date}
|
|
223
228
|
*
|
|
224
229
|
*/
|
|
225
|
-
CronDate.prototype.getDate = function () {
|
|
226
|
-
|
|
230
|
+
CronDate.prototype.getDate = function (internal) {
|
|
231
|
+
let offset = internal ? 0 : this.UTCmsOffset;
|
|
232
|
+
return new Date(this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.milliseconds-offset);
|
|
227
233
|
};
|
|
228
234
|
|
|
229
235
|
/**
|
|
230
236
|
* Convert current state back to a javascript Date() and return UTC milliseconds
|
|
231
237
|
* @public
|
|
232
|
-
*
|
|
238
|
+
* @param {boolean} internal - If this is an internal call
|
|
233
239
|
* @returns {date}
|
|
234
240
|
*
|
|
235
241
|
*/
|
|
236
|
-
CronDate.prototype.getTime = function () {
|
|
237
|
-
|
|
242
|
+
CronDate.prototype.getTime = function (internal) {
|
|
243
|
+
let offset = internal ? 0 : this.UTCmsOffset;
|
|
244
|
+
return new Date(this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.milliseconds-offset).getTime();
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* parseISOLocal
|
|
249
|
+
* @private
|
|
250
|
+
*
|
|
251
|
+
* @param {string} s - an ISO 8001 format date and time string
|
|
252
|
+
* with all components, e.g. 2015-11-24T19:40:00
|
|
253
|
+
* @returns {Date|number} - Date instance from parsing the string. May be NaN.
|
|
254
|
+
*/
|
|
255
|
+
CronDate.prototype.parseISOLocal = function (s) {
|
|
256
|
+
let b = s.split(/\D/);
|
|
257
|
+
|
|
258
|
+
// Check for completeness
|
|
259
|
+
if (b.length < 6) {
|
|
260
|
+
return NaN;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
let
|
|
264
|
+
year = parseInt(b[0], 10),
|
|
265
|
+
month = parseInt(b[1], 10),
|
|
266
|
+
day = parseInt(b[2], 10),
|
|
267
|
+
hour = parseInt(b[3], 10),
|
|
268
|
+
minute = parseInt(b[4], 10),
|
|
269
|
+
second = parseInt(b[5], 10);
|
|
270
|
+
|
|
271
|
+
// Check parts for numeric
|
|
272
|
+
if( isNaN(year) || isNaN(month) || isNaN(day) || isNaN(hour) || isNaN(minute) || isNaN(second) ) {
|
|
273
|
+
return NaN;
|
|
274
|
+
} else {
|
|
275
|
+
return new Date(year, month-1, day, hour, minute, second);
|
|
276
|
+
}
|
|
238
277
|
};
|
|
239
278
|
|
|
240
279
|
export { CronDate };
|
package/src/pattern.js
CHANGED
|
@@ -25,6 +25,7 @@ function CronPattern (pattern) {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Parse current pattern, will raise an error on failure
|
|
28
|
+
* @private
|
|
28
29
|
*/
|
|
29
30
|
CronPattern.prototype.parse = function () {
|
|
30
31
|
|
|
@@ -34,10 +35,7 @@ CronPattern.prototype.parse = function () {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
// Split configuration on whitespace
|
|
37
|
-
let parts = this.pattern.trim().replace(/\s+/g, " ").split(" ")
|
|
38
|
-
part,
|
|
39
|
-
i,
|
|
40
|
-
reValidCron = /[^/*0-9,-]+/;
|
|
38
|
+
let parts = this.pattern.trim().replace(/\s+/g, " ").split(" ");
|
|
41
39
|
|
|
42
40
|
// Validite number of configuration entries
|
|
43
41
|
if( parts.length < 5 || parts.length > 6 ) {
|
|
@@ -49,15 +47,13 @@ CronPattern.prototype.parse = function () {
|
|
|
49
47
|
parts.unshift("0");
|
|
50
48
|
}
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
|
|
51
|
+
// Replace alpha representations
|
|
52
|
+
parts[4] = this.replaceAlphaMonths(parts[4]);
|
|
53
|
+
parts[5] = this.replaceAlphaDays(parts[5]);
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
throw new TypeError("CronPattern: configuration entry " + (i + 1) + " (" + part + ") contains illegal characters.");
|
|
59
|
-
}
|
|
60
|
-
}
|
|
55
|
+
// Check part content
|
|
56
|
+
this.throwAtIllegalCharacters(parts);
|
|
61
57
|
|
|
62
58
|
// Parse parts into arrays, validates as we go
|
|
63
59
|
this.partToArray("seconds", parts[0], 0);
|
|
@@ -76,6 +72,7 @@ CronPattern.prototype.parse = function () {
|
|
|
76
72
|
|
|
77
73
|
/**
|
|
78
74
|
* 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.
|
|
75
|
+
* @private
|
|
79
76
|
*
|
|
80
77
|
* @param {CronPatternPart} type - Seconds/minutes etc
|
|
81
78
|
* @param {string} conf - Current pattern part - *, 0-1 etc
|
|
@@ -85,9 +82,6 @@ CronPattern.prototype.partToArray = function (type, conf, valueIndexOffset) {
|
|
|
85
82
|
|
|
86
83
|
let i,
|
|
87
84
|
split,
|
|
88
|
-
lower,
|
|
89
|
-
upper,
|
|
90
|
-
steps,
|
|
91
85
|
arr = this[type];
|
|
92
86
|
|
|
93
87
|
// First off, handle wildcard
|
|
@@ -98,92 +92,174 @@ CronPattern.prototype.partToArray = function (type, conf, valueIndexOffset) {
|
|
|
98
92
|
return;
|
|
99
93
|
}
|
|
100
94
|
|
|
101
|
-
//
|
|
95
|
+
// Handle separated entries (,) by recursion
|
|
102
96
|
split = conf.split(",");
|
|
103
97
|
if( split.length > 1 ) {
|
|
104
98
|
for( i = 0; i < split.length; i++ ) {
|
|
105
99
|
this.partToArray(type, split[i], valueIndexOffset);
|
|
106
100
|
}
|
|
107
|
-
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
101
|
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
102
|
+
// Handle range (-)
|
|
103
|
+
} else if( conf.indexOf("-") !== -1 ) {
|
|
104
|
+
this.handleRange(conf, type, valueIndexOffset);
|
|
114
105
|
|
|
115
|
-
|
|
106
|
+
// Handle stepping (/)
|
|
107
|
+
} else if( conf.indexOf("/") !== -1 ) {
|
|
108
|
+
this.handleStepping(conf, type, valueIndexOffset);
|
|
116
109
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
// Handle pure number
|
|
111
|
+
} else {
|
|
112
|
+
this.handleNumber(conf, type, valueIndexOffset);
|
|
113
|
+
}
|
|
120
114
|
|
|
121
|
-
|
|
122
|
-
upper = parseInt(split[1], 10) + valueIndexOffset;
|
|
115
|
+
};
|
|
123
116
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
/**
|
|
118
|
+
* After converting JAN-DEC, SUN-SAT only 0-9 * , / - are allowed, throw if anything else pops up
|
|
119
|
+
* @private
|
|
120
|
+
*
|
|
121
|
+
* @param {string[]} parts - Each part split as strings
|
|
122
|
+
*/
|
|
123
|
+
CronPattern.prototype.throwAtIllegalCharacters = function (parts) {
|
|
124
|
+
let reValidCron = /[^/*0-9,-]+/;
|
|
125
|
+
for(let i = 0; i < parts.length; i++) {
|
|
126
|
+
if( reValidCron.test(parts[i]) ) {
|
|
127
|
+
throw new TypeError("CronPattern: configuration entry " + i + " (" + parts[i] + ") contains illegal characters.");
|
|
128
128
|
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
129
131
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Nothing but a number left, handle that
|
|
134
|
+
* @private
|
|
135
|
+
*
|
|
136
|
+
* @param {string} conf - Current part, expected to be a number, as a string
|
|
137
|
+
* @param {string} type - One of "seconds", "minutes" etc
|
|
138
|
+
* @param {number} valueIndexOffset - -1 for day of month, and month, as they start at 1. 0 for seconds, hours, minutes
|
|
139
|
+
*/
|
|
140
|
+
CronPattern.prototype.handleNumber = function (conf, type, valueIndexOffset) {
|
|
141
|
+
let i = (parseInt(conf, 10) + valueIndexOffset);
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
143
|
+
if( i < 0 || i >= this[type].length ) {
|
|
144
|
+
throw new TypeError("CronPattern: " + type + " value out of range: '" + conf + "'");
|
|
145
|
+
}
|
|
139
146
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
147
|
+
this[type][i] = 1;
|
|
148
|
+
};
|
|
143
149
|
|
|
144
|
-
// - Got stepping
|
|
145
|
-
} else if( conf.indexOf("/") !== -1 ) {
|
|
146
|
-
|
|
147
|
-
split = conf.split("/");
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Take care of ranges (e.g. 1-20)
|
|
153
|
+
* @private
|
|
154
|
+
*
|
|
155
|
+
* @param {string} conf - Current part, expected to be a string like 1-20
|
|
156
|
+
* @param {string} type - One of "seconds", "minutes" etc
|
|
157
|
+
* @param {number} valueIndexOffset - -1 for day of month, and month, as they start at 1. 0 for seconds, hours, minutes
|
|
158
|
+
*/
|
|
159
|
+
CronPattern.prototype.handleRange = function (conf, type, valueIndexOffset) {
|
|
160
|
+
let split = conf.split("-");
|
|
152
161
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
if( split.length !== 2 ) {
|
|
163
|
+
throw new TypeError("CronPattern: Syntax error, illegal range: '" + conf + "'");
|
|
164
|
+
}
|
|
156
165
|
|
|
157
|
-
|
|
166
|
+
let lower = parseInt(split[0], 10) + valueIndexOffset,
|
|
167
|
+
upper = parseInt(split[1], 10) + valueIndexOffset;
|
|
158
168
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
169
|
+
if( isNaN(lower) ) {
|
|
170
|
+
throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");
|
|
171
|
+
} else if( isNaN(upper) ) {
|
|
172
|
+
throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");
|
|
173
|
+
}
|
|
162
174
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
175
|
+
// Check that value is within range
|
|
176
|
+
if( lower < 0 || upper >= this[type].length ) {
|
|
177
|
+
throw new TypeError("CronPattern: Value out of range: '" + conf + "'");
|
|
178
|
+
}
|
|
166
179
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
//
|
|
181
|
+
if( lower > upper ) {
|
|
182
|
+
throw new TypeError("CronPattern: From value is larger than to value: '" + conf + "'");
|
|
183
|
+
}
|
|
170
184
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
for( let i = lower; i <= upper; i++ ) {
|
|
186
|
+
this[type][(i + valueIndexOffset)] = 1;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
174
189
|
|
|
175
|
-
|
|
176
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Handle stepping (e.g. * / 14)
|
|
192
|
+
* @private
|
|
193
|
+
*
|
|
194
|
+
* @param {string} conf - Current part, expected to be a string like * /20 (without the space)
|
|
195
|
+
* @param {string} type - One of "seconds", "minutes" etc
|
|
196
|
+
* @param {number} valueIndexOffset - -1 for day of month, and month, as they start at 1. 0 for seconds, hours, minutes
|
|
197
|
+
*/
|
|
198
|
+
CronPattern.prototype.handleStepping = function (conf, type, valueIndexOffset) {
|
|
177
199
|
|
|
178
|
-
|
|
200
|
+
let split = conf.split("/");
|
|
179
201
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
202
|
+
if( split.length !== 2 ) {
|
|
203
|
+
throw new TypeError("CronPattern: Syntax error, illegal stepping: '" + conf + "'");
|
|
204
|
+
}
|
|
183
205
|
|
|
184
|
-
|
|
206
|
+
if( split[0] !== "*" ) {
|
|
207
|
+
throw new TypeError("CronPattern: Syntax error, left part of / needs to be * : '" + conf + "'");
|
|
185
208
|
}
|
|
186
209
|
|
|
210
|
+
let steps = parseInt(split[1], 10);
|
|
211
|
+
|
|
212
|
+
if( isNaN(steps) ) throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");
|
|
213
|
+
if( steps === 0 ) throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");
|
|
214
|
+
if( steps > this[type].length ) throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[type].length+")");
|
|
215
|
+
|
|
216
|
+
for( let i = 0; i < this[type].length; i+= steps ) {
|
|
217
|
+
this[type][(i + valueIndexOffset)] = 1;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Replace day name with day numbers
|
|
224
|
+
* @private
|
|
225
|
+
*
|
|
226
|
+
* @param {string} conf - Current part, expected to be a string that might contain sun,mon etc.
|
|
227
|
+
*
|
|
228
|
+
* @returns {string} - conf with 0 instead of sun etc.
|
|
229
|
+
*/
|
|
230
|
+
CronPattern.prototype.replaceAlphaDays = function (conf) {
|
|
231
|
+
return conf
|
|
232
|
+
.replace(/sun/gi, "0")
|
|
233
|
+
.replace(/mon/gi, "1")
|
|
234
|
+
.replace(/tue/gi, "2")
|
|
235
|
+
.replace(/wed/gi, "3")
|
|
236
|
+
.replace(/thu/gi, "4")
|
|
237
|
+
.replace(/fri/gi, "5")
|
|
238
|
+
.replace(/sat/gi, "6");
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Replace month name with month numbers
|
|
243
|
+
* @private
|
|
244
|
+
*
|
|
245
|
+
* @param {string} conf - Current part, expected to be a string that might contain jan,feb etc.
|
|
246
|
+
*
|
|
247
|
+
* @returns {string} - conf with 0 instead of sun etc.
|
|
248
|
+
*/
|
|
249
|
+
CronPattern.prototype.replaceAlphaMonths = function (conf) {
|
|
250
|
+
return conf
|
|
251
|
+
.replace(/jan/gi, "1")
|
|
252
|
+
.replace(/feb/gi, "2")
|
|
253
|
+
.replace(/mar/gi, "3")
|
|
254
|
+
.replace(/apr/gi, "4")
|
|
255
|
+
.replace(/may/gi, "5")
|
|
256
|
+
.replace(/jun/gi, "6")
|
|
257
|
+
.replace(/jul/gi, "7")
|
|
258
|
+
.replace(/aug/gi, "8")
|
|
259
|
+
.replace(/sep/gi, "9")
|
|
260
|
+
.replace(/oct/gi, "10")
|
|
261
|
+
.replace(/nov/gi, "11")
|
|
262
|
+
.replace(/dec/gi, "12");
|
|
187
263
|
};
|
|
188
264
|
|
|
189
265
|
export { CronPattern };
|
package/test/src/suite.cjs
CHANGED
|
@@ -343,21 +343,18 @@ module.exports = function (Cron) {
|
|
|
343
343
|
nextRun;
|
|
344
344
|
|
|
345
345
|
// Set a fixed hour later than startAt, to be sure that the days doesn't overlap
|
|
346
|
-
nextDay = new Date(nextDay.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
scheduler = new Cron("0 0 12 * * *", { startAt: nextDay });
|
|
346
|
+
nextDay = new Date(nextDay.setUTCHours(13));
|
|
347
|
+
scheduler = new Cron("0 0 12 * * *", {timezone: "Etc/UTC", startAt: nextDay.toISOString() });
|
|
350
348
|
nextRun = scheduler.next();
|
|
351
349
|
|
|
352
350
|
// Set seconds, minutes and hours to 00:00:00
|
|
353
351
|
dayAfterNext.setMilliseconds(0);
|
|
354
|
-
dayAfterNext.
|
|
355
|
-
dayAfterNext.
|
|
356
|
-
dayAfterNext.
|
|
352
|
+
dayAfterNext.setUTCSeconds(0);
|
|
353
|
+
dayAfterNext.setUTCMinutes(0);
|
|
354
|
+
dayAfterNext.setUTCHours(12);
|
|
357
355
|
|
|
358
356
|
// Do comparison
|
|
359
357
|
nextRun.getTime().should.equal(dayAfterNext.getTime());
|
|
360
|
-
|
|
361
358
|
|
|
362
359
|
});
|
|
363
360
|
|
|
@@ -390,7 +387,7 @@ module.exports = function (Cron) {
|
|
|
390
387
|
it("0 0 12 * * * with stopdate yesterday should return undefined", function () {
|
|
391
388
|
let
|
|
392
389
|
dayBefore = new Date(new Date().getTime()-24*60*60*1000), // Subtract one day
|
|
393
|
-
scheduler = new Cron("0 0 12 * * *", { stopAt: dayBefore }),
|
|
390
|
+
scheduler = new Cron("0 0 12 * * *", { timezone: "Etc/UTC", stopAt: dayBefore.toISOString() }),
|
|
394
391
|
nextRun = scheduler.next();
|
|
395
392
|
|
|
396
393
|
// Do comparison
|
|
@@ -456,15 +453,6 @@ module.exports = function (Cron) {
|
|
|
456
453
|
|
|
457
454
|
});
|
|
458
455
|
|
|
459
|
-
it("Valid startAt with Date should not throw", function () {
|
|
460
|
-
(function () {
|
|
461
|
-
let
|
|
462
|
-
dayBefore = new Date(new Date().getTime()-24*60*60*1000), // Subtract one day
|
|
463
|
-
scheduler = new Cron("0 0 12 * * *", { startAt: dayBefore });
|
|
464
|
-
scheduler.next();
|
|
465
|
-
}).should.not.throw();
|
|
466
|
-
});
|
|
467
|
-
|
|
468
456
|
it("Valid startAt with DateTime string should not throw", function () {
|
|
469
457
|
(function () {
|
|
470
458
|
let
|
|
@@ -473,12 +461,12 @@ module.exports = function (Cron) {
|
|
|
473
461
|
}).should.not.throw();
|
|
474
462
|
});
|
|
475
463
|
|
|
476
|
-
it("
|
|
464
|
+
it("startAt with Date string should throw", function () {
|
|
477
465
|
(function () {
|
|
478
466
|
let
|
|
479
467
|
scheduler = new Cron("0 0 12 * * *", { startAt: "2016-12-01" });
|
|
480
468
|
scheduler.next();
|
|
481
|
-
}).should.
|
|
469
|
+
}).should.throw();
|
|
482
470
|
});
|
|
483
471
|
|
|
484
472
|
it("Invalid startat should throw", function () {
|
|
@@ -514,12 +502,12 @@ module.exports = function (Cron) {
|
|
|
514
502
|
}).should.not.throw();
|
|
515
503
|
});
|
|
516
504
|
|
|
517
|
-
it("Valid stopAt with Date string should
|
|
505
|
+
it("Valid stopAt with Date string should throw", function () {
|
|
518
506
|
(function () {
|
|
519
507
|
let
|
|
520
508
|
scheduler = new Cron("0 0 12 * * *", { stopAt: "2016-12-01" });
|
|
521
509
|
scheduler.next();
|
|
522
|
-
}).should.
|
|
510
|
+
}).should.throw();
|
|
523
511
|
});
|
|
524
512
|
|
|
525
513
|
it("Invalid stopAt should throw", function () {
|
|
@@ -567,14 +555,15 @@ module.exports = function (Cron) {
|
|
|
567
555
|
diff;
|
|
568
556
|
|
|
569
557
|
target.getTime().should.equal(scheduler.next().getTime());
|
|
570
|
-
|
|
571
558
|
if(target.getTime() === scheduler.next().getTime()) {
|
|
572
559
|
while(prevRun < target) {
|
|
573
560
|
left = scheduler.msToNext(prevRun);
|
|
574
561
|
diff = Math.abs((target.getTime() - prevRun.getTime())-left);
|
|
575
562
|
diff.should.be.below(1001);
|
|
576
563
|
diff.should.be.above(-1);
|
|
577
|
-
|
|
564
|
+
|
|
565
|
+
// Advance 1000s
|
|
566
|
+
prevRun.setMilliseconds(1000000);
|
|
578
567
|
}
|
|
579
568
|
}
|
|
580
569
|
|
|
@@ -595,13 +584,14 @@ module.exports = function (Cron) {
|
|
|
595
584
|
diff = Math.abs((target.getTime() - prevRun.getTime())-left);
|
|
596
585
|
diff.should.be.below(1001);
|
|
597
586
|
diff.should.be.above(-1);
|
|
598
|
-
|
|
587
|
+
|
|
588
|
+
// Advance 1000s
|
|
589
|
+
prevRun.setMilliseconds(1000000);
|
|
599
590
|
}
|
|
600
591
|
}
|
|
601
592
|
|
|
602
593
|
});
|
|
603
594
|
it("Test when next thursday 1st november occurr, starting from 2021-10-13 00:00:00", function () {
|
|
604
|
-
//Cron("0 0 0 1 11 4").next(new Date(1634076000000)).getTime().should.equal(1888182000000);
|
|
605
595
|
Cron("0 0 0 1 11 4").next(new Date(1634076000000)).getFullYear().should.equal(2029);
|
|
606
596
|
});
|
|
607
597
|
it("getTime should return expcted difference with different timezones (now)", function () {
|
|
@@ -609,24 +599,25 @@ module.exports = function (Cron) {
|
|
|
609
599
|
timeNewYork = Cron("* * * * * *", {timezone: "America/New_York"}).next(new Date()).getTime();
|
|
610
600
|
|
|
611
601
|
// The time right now should be the same in utc wether in new york or stockholm
|
|
612
|
-
timeStockholm.should.be.above(timeNewYork-
|
|
613
|
-
timeStockholm.should.be.below(timeNewYork+
|
|
602
|
+
timeStockholm.should.be.above(timeNewYork-4000);
|
|
603
|
+
timeStockholm.should.be.below(timeNewYork+4000);
|
|
614
604
|
});
|
|
615
|
-
|
|
605
|
+
it("getTime should return expcted difference with different timezones (net sunday 1st november)", function () {
|
|
616
606
|
let timeStockholm = Cron("* * * 1 11 4", {timezone: "Europe/Stockholm"}).next(new Date(1634076000000)).getTime(),
|
|
617
|
-
timeNewYork = Cron("* * * 1 11 4", {timezone: "America/New_York"}).next(new Date(1634076000000)).getTime()
|
|
607
|
+
timeNewYork = Cron("* * * 1 11 4", {timezone: "America/New_York"}).next(new Date(1634076000000)).getTime(),
|
|
608
|
+
diff = (timeNewYork-timeStockholm)/1000/3600;
|
|
618
609
|
|
|
619
610
|
// The time when next sunday 1st november occur should be with 6 hours difference (seen from utc)
|
|
620
|
-
|
|
621
|
-
})
|
|
611
|
+
diff.should.equal(6);
|
|
612
|
+
});
|
|
622
613
|
it("maxRuns should be inherited from scheduler to job", function () {
|
|
623
614
|
let scheduler = Cron("* * * 1 11 4", {maxRuns: 14}),
|
|
624
615
|
job = scheduler.schedule(() => {});
|
|
625
616
|
job.options.maxRuns.should.equal(14);
|
|
626
617
|
job.stop();
|
|
627
618
|
});
|
|
628
|
-
it("Next saturday at 29th of february should occur 2048", function () {
|
|
629
|
-
let nextSaturday29feb = Cron("0 0 0 29
|
|
619
|
+
it("Next saturday at 29th of february should occur 2048. Also test weekday an month names and case insensitivity", function () {
|
|
620
|
+
let nextSaturday29feb = Cron("0 0 0 29 feb SAT").next(new Date(1634076000000));
|
|
630
621
|
nextSaturday29feb.getFullYear().should.equal(2048);
|
|
631
622
|
});
|
|
632
623
|
it("Impossible combination should result in null", function () {
|
package/types/croner.d.ts
CHANGED
|
@@ -103,25 +103,27 @@ export class Cron {
|
|
|
103
103
|
next(prev?: Date): Date | null;
|
|
104
104
|
/**
|
|
105
105
|
* Return previous run time
|
|
106
|
+
* @public
|
|
106
107
|
*
|
|
107
|
-
* @returns {
|
|
108
|
+
* @returns {CronDate | null} - Previous run time
|
|
108
109
|
*/
|
|
109
|
-
previous():
|
|
110
|
+
public previous(): CronDate | null;
|
|
110
111
|
private _next;
|
|
111
112
|
/**
|
|
112
113
|
* Returns number of milliseconds to next run
|
|
114
|
+
* @public
|
|
113
115
|
*
|
|
114
116
|
* @param {CronNextResult} [prev=new CronDate()] - Starting date, defaults to now
|
|
115
117
|
* @returns {number | null}
|
|
116
118
|
*/
|
|
117
|
-
msToNext(prev?: CronNextResult): number | null;
|
|
119
|
+
public msToNext(prev?: CronNextResult): number | null;
|
|
118
120
|
/**
|
|
119
121
|
* Stop execution
|
|
120
122
|
* @public
|
|
121
123
|
*/
|
|
122
124
|
public stop(): void;
|
|
123
125
|
/**
|
|
124
|
-
* Pause
|
|
126
|
+
* Pause executionR
|
|
125
127
|
* @public
|
|
126
128
|
*
|
|
127
129
|
* @returns {boolean} - Wether pause was successful
|
package/types/date.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Converts date to CronDate
|
|
3
3
|
* @constructor
|
|
4
4
|
*
|
|
5
|
-
* @param {date|string} [date] - Input date
|
|
5
|
+
* @param {date|string} [date] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected
|
|
6
6
|
* @param {string} [timezone] - String representation of timezone in Europe/Stockholm format.
|
|
7
7
|
*/
|
|
8
8
|
export function CronDate(date?: any, timezone?: string): void;
|
|
@@ -11,7 +11,7 @@ export class CronDate {
|
|
|
11
11
|
* Converts date to CronDate
|
|
12
12
|
* @constructor
|
|
13
13
|
*
|
|
14
|
-
* @param {date|string} [date] - Input date
|
|
14
|
+
* @param {date|string} [date] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected
|
|
15
15
|
* @param {string} [timezone] - String representation of timezone in Europe/Stockholm format.
|
|
16
16
|
*/
|
|
17
17
|
constructor(date?: any, timezone?: string);
|
|
@@ -40,16 +40,18 @@ export class CronDate {
|
|
|
40
40
|
* Convert current state back to a javascript Date()
|
|
41
41
|
* @public
|
|
42
42
|
*
|
|
43
|
+
* @param {boolean} internal - If this is an internal call
|
|
43
44
|
* @returns {date}
|
|
44
45
|
*
|
|
45
46
|
*/
|
|
46
|
-
public getDate(): any;
|
|
47
|
+
public getDate(internal: boolean): any;
|
|
47
48
|
/**
|
|
48
49
|
* Convert current state back to a javascript Date() and return UTC milliseconds
|
|
49
50
|
* @public
|
|
50
|
-
*
|
|
51
|
+
* @param {boolean} internal - If this is an internal call
|
|
51
52
|
* @returns {date}
|
|
52
53
|
*
|
|
53
54
|
*/
|
|
54
|
-
public getTime(): any;
|
|
55
|
+
public getTime(internal: boolean): any;
|
|
56
|
+
private parseISOLocal;
|
|
55
57
|
}
|
package/types/pattern.d.ts
CHANGED
|
@@ -28,16 +28,12 @@ export class CronPattern {
|
|
|
28
28
|
days: any[];
|
|
29
29
|
months: any[];
|
|
30
30
|
daysOfWeek: any[];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* @param {string} conf - Current pattern part - *, 0-1 etc
|
|
40
|
-
* @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
|
|
41
|
-
*/
|
|
42
|
-
partToArray(type: CronPatternPart, conf: string, valueIndexOffset: CronIndexOffset): void;
|
|
31
|
+
private parse;
|
|
32
|
+
private partToArray;
|
|
33
|
+
private throwAtIllegalCharacters;
|
|
34
|
+
private handleNumber;
|
|
35
|
+
private handleRange;
|
|
36
|
+
private handleStepping;
|
|
37
|
+
private replaceAlphaDays;
|
|
38
|
+
private replaceAlphaMonths;
|
|
43
39
|
}
|