croner 4.4.1 → 5.0.0
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/README.md +13 -13
- package/SECURITY.md +1 -1
- package/dist/croner.cjs +269 -173
- package/dist/croner.min.js +1 -1
- package/dist/croner.min.js.map +1 -1
- package/dist/croner.min.mjs +1 -1
- package/dist/croner.min.mjs.map +1 -1
- package/package.json +1 -1
- package/src/croner.js +4 -4
- package/src/date.js +25 -104
- package/src/minitz.js +286 -0
- package/src/options.js +2 -2
- package/types/date.d.ts +1 -3
- package/types/minitz.d.ts +183 -0
- package/types/options.d.ts +2 -2
- package/src/tz.js +0 -110
- package/types/tz.d.ts +0 -38
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Trigger functions and/or evaluate cron expressions in JavaScript. No dependencie
|
|
|
14
14
|
* Works in Node.js >=6.0 (both require and import).
|
|
15
15
|
* Works in Deno >=1.16.
|
|
16
16
|
* Works in browsers as standalone, UMD or ES-module.
|
|
17
|
-
*
|
|
17
|
+
* Schedule using specific target timezones.
|
|
18
18
|
* Includes [TypeScript](https://www.typescriptlang.org/) typings.
|
|
19
19
|
|
|
20
20
|
Quick examples:
|
|
@@ -120,7 +120,7 @@ const job : Cron = new Cron("* * * * * *", () => {
|
|
|
120
120
|
JavaScript
|
|
121
121
|
|
|
122
122
|
```javascript
|
|
123
|
-
import Cron from "https://
|
|
123
|
+
import Cron from "https://deno.land/x/croner@5.0.0/src/croner.js";
|
|
124
124
|
|
|
125
125
|
Cron("* * * * * *", () => {
|
|
126
126
|
console.log("This will run every second.");
|
|
@@ -130,7 +130,7 @@ Cron("* * * * * *", () => {
|
|
|
130
130
|
TypeScript
|
|
131
131
|
|
|
132
132
|
```typescript
|
|
133
|
-
import { Cron } from "https://
|
|
133
|
+
import { Cron } from "https://deno.land/x/croner@5.0.0/src/croner.js";
|
|
134
134
|
|
|
135
135
|
const _scheduler : Cron = new Cron("* * * * * *", () => {
|
|
136
136
|
console.log("This will run every second.");
|
|
@@ -150,14 +150,14 @@ const _scheduler : Cron = new Cron("* * * * * *", () => {
|
|
|
150
150
|
To use as a [UMD](https://github.com/umdjs/umd)-module (stand alone, [RequireJS](https://requirejs.org/) etc.)
|
|
151
151
|
|
|
152
152
|
```html
|
|
153
|
-
<script src="https://cdn.jsdelivr.net/npm/croner@
|
|
153
|
+
<script src="https://cdn.jsdelivr.net/npm/croner@5/dist/croner.min.js"></script>
|
|
154
154
|
```
|
|
155
155
|
|
|
156
156
|
To use as a [ES-module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
|
|
157
157
|
|
|
158
158
|
```html
|
|
159
159
|
<script type="module">
|
|
160
|
-
import Cron from "https://cdn.jsdelivr.net/npm/croner@
|
|
160
|
+
import Cron from "https://cdn.jsdelivr.net/npm/croner@5/dist/croner.min.mjs";
|
|
161
161
|
|
|
162
162
|
// ... see usage section ...
|
|
163
163
|
</script>
|
|
@@ -203,18 +203,18 @@ job.stop();
|
|
|
203
203
|
| maxRuns | Infinite | Number | |
|
|
204
204
|
| catch | false | Boolean | Catch and ignore unhandled errors in triggered function |
|
|
205
205
|
| timezone | undefined | String | Timezone in Europe/Stockholm format |
|
|
206
|
-
| startAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local
|
|
207
|
-
| stopAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local
|
|
206
|
+
| startAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local time (according to timezone parameter if passed) |
|
|
207
|
+
| stopAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local time (according to timezone parameter if passed) |
|
|
208
208
|
| interval | 0 | Number | Minimum number of seconds between triggers. |
|
|
209
209
|
| paused | false | Boolean | If the job should be paused from start. |
|
|
210
210
|
| context | undefined | Any | Passed as the second parameter to triggered function |
|
|
211
|
-
| legacyMode |
|
|
211
|
+
| legacyMode | true | boolean | Combine day-of-month and day-of-week using true = OR, false = AND |
|
|
212
212
|
|
|
213
213
|
#### Pattern
|
|
214
214
|
|
|
215
215
|
The expressions of Croner are very similar to the ones of Vixie Cron, with a few additions and changes listed below.
|
|
216
216
|
|
|
217
|
-
* In croner, a combination of day-of-week and day-of-month will only trigger when both conditions match. An example: ```0 20 1 * MON``` will only trigger when monday occur the first day of any month. In Vixie Cron, it would trigger every monday AND the first day of every month. Vixie style can be enabled with `legacyMode: true` from version `4.2.0`. See issue [#53](https://github.com/Hexagon/croner/issues/53) for more information.
|
|
217
|
+
* In croner, a combination of day-of-week and day-of-month will only trigger when both conditions match. An example: ```0 20 1 * MON``` will only trigger when monday occur the first day of any month. In Vixie Cron, it would trigger every monday AND the first day of every month. Vixie style can be enabled with `legacyMode: true` from version `4.2.0` and is default from `5.0.0`. See issue [#53](https://github.com/Hexagon/croner/issues/53) for more information.
|
|
218
218
|
|
|
219
219
|
* Croner expressions support the following additional modifiers
|
|
220
220
|
- *?* A question mark is substituted with croner initialization time, as an example - `? ? * * * *` would be substituted with `25 8 * * * *` if time is `<any hour>:08:25` at the time of `new Cron('? ? * * * *', <...>)`. The question mark can be used in any field.
|
|
@@ -261,7 +261,7 @@ It is also possible to use the following "nicknames" as pattern.
|
|
|
261
261
|
#### Expressions
|
|
262
262
|
```javascript
|
|
263
263
|
// Run a function according to pattern
|
|
264
|
-
Cron('15-45/10 */5 1,2,3 ? JAN-MAR SAT', function () {
|
|
264
|
+
Cron('15-45/10 */5 1,2,3 ? JAN-MAR SAT', { legacyMode: false }, function () {
|
|
265
265
|
console.log('This will run every tenth second between second 15-45');
|
|
266
266
|
console.log('every fifth minute of hour 1,2 and 3 when day of month');
|
|
267
267
|
console.log('is the same as when Cron started, every saturday in January to March.');
|
|
@@ -271,7 +271,7 @@ Cron('15-45/10 */5 1,2,3 ? JAN-MAR SAT', function () {
|
|
|
271
271
|
#### Interval
|
|
272
272
|
```javascript
|
|
273
273
|
// Trigger on specific interval combined with cron expression
|
|
274
|
-
Cron('* * * 7-16 * MON-FRI', { interval: 90 }, function () {
|
|
274
|
+
Cron('* * * 7-16 * MON-FRI', { interval: 90, legacyMode: false }, function () {
|
|
275
275
|
console.log('This will trigger every 90th second at 7-16 on mondays to fridays.');
|
|
276
276
|
});
|
|
277
277
|
```
|
|
@@ -281,8 +281,8 @@ Cron('* * * 7-16 * MON-FRI', { interval: 90 }, function () {
|
|
|
281
281
|
// Find next month
|
|
282
282
|
const nextMonth = Cron("@monthly").next(),
|
|
283
283
|
nextSunday = Cron("@weekly").next(),
|
|
284
|
-
nextSat29feb = Cron("0 0 0 29 2 6").next(),
|
|
285
|
-
nextSunLastOfMonth = Cron("0 0 0 L * 7").next();
|
|
284
|
+
nextSat29feb = Cron("0 0 0 29 2 6", { legacyMode: false }).next(),
|
|
285
|
+
nextSunLastOfMonth = Cron("0 0 0 L * 7", { legacyMode: false }).next();
|
|
286
286
|
|
|
287
287
|
console.log("First day of next month: " + nextMonth.toLocaleDateString());
|
|
288
288
|
console.log("Next sunday: " + nextSunday.toLocaleDateString());
|
package/SECURITY.md
CHANGED
package/dist/croner.cjs
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
/* ------------------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
-
minitz
|
|
9
|
+
minitz 2.1.3 - MIT License - Hexagon <hexagon@56k.guru>
|
|
10
10
|
|
|
11
|
-
Bundled manually, check
|
|
11
|
+
Bundled manually, check https://github.com/Hexagon/minitz for updates
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
------------------------------------------------------------------------------------
|
|
14
14
|
|
|
15
15
|
License:
|
|
16
16
|
|
|
@@ -26,91 +26,266 @@
|
|
|
26
26
|
all copies or substantial portions of the Software.
|
|
27
27
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
28
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
29
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
30
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
31
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
32
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
33
33
|
THE SOFTWARE.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
------------------------------------------------------------------------------------ */
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} TimePoint
|
|
39
|
+
* @property {Number} year - 1970--
|
|
40
|
+
* @property {Number} month - 1-12
|
|
41
|
+
* @property {Number} day - 1-31
|
|
42
|
+
* @property {Number} hour - 0-24
|
|
43
|
+
* @property {Number} minute - 0-60
|
|
44
|
+
* @property {Number} second - 0-60
|
|
45
|
+
* @property {string} timezone - Time zone in IANA database format 'Europe/Stockholm'
|
|
46
|
+
*/
|
|
38
47
|
|
|
39
48
|
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
minitz
|
|
60
|
-
return
|
|
49
|
+
* Converts a date/time from a specific timezone to a normal date object using the system local time
|
|
50
|
+
*
|
|
51
|
+
* Shortcut for minitz.fromTZ(minitz.tp(...));
|
|
52
|
+
*
|
|
53
|
+
* @constructor
|
|
54
|
+
*
|
|
55
|
+
* @param {Number} year - 1970--
|
|
56
|
+
* @param {Number} month - 1-12
|
|
57
|
+
* @param {Number} day - 1-31
|
|
58
|
+
* @param {Number} hour - 0-24
|
|
59
|
+
* @param {Number} minute - 0-60
|
|
60
|
+
* @param {Number} second - 0-60
|
|
61
|
+
* @param {string} timezone - Time zone in IANA database format 'Europe/Stockholm'
|
|
62
|
+
* @param {boolean} [throwOnInvalidTime] - Default is to return the adjusted time if the call happens during a Daylight-Saving-Time switch.
|
|
63
|
+
* E.g. Value "01:01:01" is returned if input time is 00:01:01 while one hour got actually
|
|
64
|
+
* skipped, going from 23:59:59 to 01:00:00. Setting this flag makes the library throw an exception instead.
|
|
65
|
+
* @returns {date} - Normal date object with correct UTC and system local time
|
|
66
|
+
*
|
|
67
|
+
*/
|
|
68
|
+
function minitz(year, month, day, hour, minute, second, timezone, throwOnInvalidTime) {
|
|
69
|
+
return minitz.fromTZ(minitz.tp(year, month, day, hour, minute, second, timezone), throwOnInvalidTime);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Converts a date/time from a specific timezone to a normal date object using the system local time
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
* @static
|
|
77
|
+
*
|
|
78
|
+
* @param {string} localTimeString - ISO8601 formatted local time string, non UTC
|
|
79
|
+
* @param {string} timezone - Time zone in IANA database format 'Europe/Stockholm'
|
|
80
|
+
* @param {boolean} [throwOnInvalidTime] - Default is to return the adjusted time if the call happens during a Daylight-Saving-Time switch.
|
|
81
|
+
* E.g. Value "01:01:01" is returned if input time is 00:01:01 while one hour got actually
|
|
82
|
+
* skipped, going from 23:59:59 to 01:00:00. Setting this flag makes the library throw an exception instead.
|
|
83
|
+
* @return {date} - Normal date object
|
|
84
|
+
*
|
|
85
|
+
*/
|
|
86
|
+
minitz.fromTZISO = (localTimeString, timezone, throwOnInvalidTime) => {
|
|
87
|
+
return minitz.fromTZ(parseISOLocal(localTimeString, timezone), throwOnInvalidTime);
|
|
61
88
|
};
|
|
62
|
-
|
|
89
|
+
|
|
63
90
|
/**
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
minitz.fromTZ = function(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
* Converts a date/time from a specific timezone to a normal date object using the system local time
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
* @static
|
|
95
|
+
*
|
|
96
|
+
* @param {TimePoint} date - Object with specified timezone
|
|
97
|
+
* @param {boolean} [throwOnInvalidTime] - Default is to return the adjusted time if the call happens during a Daylight-Saving-Time switch.
|
|
98
|
+
* E.g. Value "01:01:01" is returned if input time is 00:01:01 while one hour got actually
|
|
99
|
+
* skipped, going from 23:59:59 to 01:00:00. Setting this flag makes the library throw an exception instead.
|
|
100
|
+
* @returns {date} - Normal date object
|
|
101
|
+
*/
|
|
102
|
+
minitz.fromTZ = function(timePoint, throwOnInvalidTime) {
|
|
103
|
+
|
|
104
|
+
const
|
|
105
|
+
|
|
106
|
+
// Construct a fake Date object with UTC date/time set to local date/time in source timezone
|
|
107
|
+
inputDate = new Date(Date.UTC(
|
|
108
|
+
timePoint.year,
|
|
109
|
+
timePoint.month - 1,
|
|
110
|
+
timePoint.day,
|
|
111
|
+
timePoint.hour,
|
|
112
|
+
timePoint.minute,
|
|
113
|
+
timePoint.second
|
|
114
|
+
)),
|
|
115
|
+
|
|
116
|
+
// Get offset between UTC and source timezone
|
|
117
|
+
offset = getTimezoneOffset(timePoint.timezone, inputDate),
|
|
118
|
+
|
|
119
|
+
// Remove offset from inputDate to hopefully get a true date object
|
|
120
|
+
guessedLocalDate = new Date(inputDate.getTime() - offset),
|
|
121
|
+
|
|
122
|
+
// Get offset between UTC and guessed time in target timezone
|
|
123
|
+
guessedInputDateOffset = getTimezoneOffset(timePoint.timezone, guessedLocalDate);
|
|
124
|
+
|
|
125
|
+
// If offset between guessed true date object and UTC matches initial calculation, the guess
|
|
126
|
+
// was spot on
|
|
127
|
+
if ((guessedInputDateOffset - offset) === 0) {
|
|
91
128
|
return guessedLocalDate;
|
|
92
129
|
} else {
|
|
93
|
-
// Not quite there yet, make a second try on guessing local time, adjust by the offset
|
|
130
|
+
// Not quite there yet, make a second try on guessing the local time, adjust by the offset indicated by the previous guess
|
|
94
131
|
// Try recreating input time again
|
|
95
|
-
// Then calculate and check offset again
|
|
96
|
-
const
|
|
97
|
-
guessedLocalDate2 = new Date(inputDate.getTime()
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (guessedInputDateOffset2 === 0) {
|
|
132
|
+
// Then calculate and check the offset again
|
|
133
|
+
const
|
|
134
|
+
guessedLocalDate2 = new Date(inputDate.getTime() - guessedInputDateOffset),
|
|
135
|
+
guessedInputDateOffset2 = getTimezoneOffset(timePoint.timezone, guessedLocalDate2);
|
|
136
|
+
if ((guessedInputDateOffset2 - guessedInputDateOffset) === 0) {
|
|
101
137
|
// All good, return local time
|
|
102
138
|
return guessedLocalDate2;
|
|
103
139
|
} else if (!throwOnInvalidTime) {
|
|
104
|
-
//
|
|
140
|
+
// This guess wasn't spot on either, we're most probably dealing with a DST transition
|
|
141
|
+
// - return the local time adjusted by _initial_ offset
|
|
105
142
|
return guessedLocalDate;
|
|
106
143
|
} else {
|
|
107
144
|
// Input time is invalid, and the library is instructed to throw, so let's do it
|
|
108
145
|
throw new Error("Invalid date passed to fromTZ()");
|
|
109
146
|
}
|
|
110
147
|
}
|
|
148
|
+
};
|
|
111
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Converts a date to a specific time zone and returns an object containing year, month,
|
|
152
|
+
* day, hour, (...) and timezone used for the conversion
|
|
153
|
+
*
|
|
154
|
+
* **Please note**: If you just want to _display_ date/time in another
|
|
155
|
+
* time zone, use vanilla JS. See the example below.
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
* @static
|
|
159
|
+
*
|
|
160
|
+
* @param {date} date - Input date
|
|
161
|
+
* @param {string} [tzString] - Timezone string in Europe/Stockholm format
|
|
162
|
+
*
|
|
163
|
+
* @returns {TimePoint}
|
|
164
|
+
*
|
|
165
|
+
* @example <caption>Example using minitz:</caption>
|
|
166
|
+
* let normalDate = new Date(); // d is a normal Date instance, with local timezone and correct utc representation
|
|
167
|
+
*
|
|
168
|
+
* tzDate = minitz.toTZ(d, 'America/New_York');
|
|
169
|
+
*
|
|
170
|
+
* // Will result in the following object:
|
|
171
|
+
* // {
|
|
172
|
+
* // year: 2022,
|
|
173
|
+
* // month: 9,
|
|
174
|
+
* // day: 28,
|
|
175
|
+
* // hour: 13,
|
|
176
|
+
* // minute: 28,
|
|
177
|
+
* // second: 28,
|
|
178
|
+
* // timezone: "America/New_York"
|
|
179
|
+
* // }
|
|
180
|
+
*
|
|
181
|
+
* @example <caption>Example using vanilla js:</caption>
|
|
182
|
+
* console.log(
|
|
183
|
+
* // Display current time in America/New_York, using sv-SE locale
|
|
184
|
+
* new Date().toLocaleTimeString("sv-SE", { timeZone: "America/New_York" }),
|
|
185
|
+
* );
|
|
186
|
+
*
|
|
187
|
+
*/
|
|
188
|
+
minitz.toTZ = function (date, tzString) {
|
|
189
|
+
const target = new Date(date.toLocaleString("sv-SE", {timeZone: tzString}));
|
|
190
|
+
return {
|
|
191
|
+
year: target.getFullYear(),
|
|
192
|
+
month: target.getMonth() + 1,
|
|
193
|
+
day: target.getDate(),
|
|
194
|
+
hour: target.getHours(),
|
|
195
|
+
minute: target.getMinutes(),
|
|
196
|
+
second: target.getSeconds(),
|
|
197
|
+
timezone: tzString
|
|
198
|
+
};
|
|
112
199
|
};
|
|
113
|
-
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Convenience function which returns a TimePoint object for later use in fromTZ
|
|
203
|
+
*
|
|
204
|
+
* @public
|
|
205
|
+
* @static
|
|
206
|
+
*
|
|
207
|
+
* @param {Number} year - 1970--
|
|
208
|
+
* @param {Number} month - 1-12
|
|
209
|
+
* @param {Number} day - 1-31
|
|
210
|
+
* @param {Number} hour - 0-24
|
|
211
|
+
* @param {Number} minute - 0-60
|
|
212
|
+
* @param {Number} second - 0-60
|
|
213
|
+
* @param {string} timezone - Time zone in format 'Europe/Stockholm'
|
|
214
|
+
*
|
|
215
|
+
* @returns {TimePoint}
|
|
216
|
+
*
|
|
217
|
+
*/
|
|
218
|
+
minitz.tp = (y,m,d,h,i,s,t) => { return { year: y, month: m, day: d, hour: h, minute: i, second: s, timezone: t }; };
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Helper function that returns the current UTC offset (in ms) for a specific timezone at a specific point in time
|
|
222
|
+
*
|
|
223
|
+
* @private
|
|
224
|
+
*
|
|
225
|
+
* @param {timeZone} string - Target time zone in IANA database format 'Europe/Stockholm'
|
|
226
|
+
* @param {date} [date] - Point in time to use as base for offset calculation
|
|
227
|
+
*
|
|
228
|
+
* @returns {number} - Offset in ms between UTC and timeZone
|
|
229
|
+
*/
|
|
230
|
+
function getTimezoneOffset(timeZone, date = new Date()) {
|
|
231
|
+
const tz = date.toLocaleString("en", {timeZone, timeStyle: "long"}).split(" ").slice(-1)[0];
|
|
232
|
+
const dateString = date.toString();
|
|
233
|
+
return Date.parse(`${dateString} UTC`) - Date.parse(`${dateString} ${tz}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Helper function that takes a ISO8001 local date time string and creates a Date object.
|
|
239
|
+
* Throws on failure. Throws on invalid date or time.
|
|
240
|
+
*
|
|
241
|
+
* @private
|
|
242
|
+
*
|
|
243
|
+
* @param {string} dateTimeString - an ISO 8601 format date and time string
|
|
244
|
+
* with all components, e.g. 2015-11-24T19:40:00
|
|
245
|
+
* @returns {TimePoint} - TimePoint instance from parsing the string
|
|
246
|
+
*/
|
|
247
|
+
function parseISOLocal(dateTimeString, timezone) {
|
|
248
|
+
const dateTimeStringSplit = dateTimeString.split(/\D/);
|
|
249
|
+
|
|
250
|
+
// Check for completeness
|
|
251
|
+
if (dateTimeStringSplit.length < 6) {
|
|
252
|
+
throw new Error("minitz: Incomplete ISO8601 passed to parser.");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const
|
|
256
|
+
year = parseInt(dateTimeStringSplit[0], 10),
|
|
257
|
+
month = parseInt(dateTimeStringSplit[1], 10),
|
|
258
|
+
day = parseInt(dateTimeStringSplit[2], 10),
|
|
259
|
+
hour = parseInt(dateTimeStringSplit[3], 10),
|
|
260
|
+
minute = parseInt(dateTimeStringSplit[4], 10),
|
|
261
|
+
second = parseInt(dateTimeStringSplit[5], 10);
|
|
262
|
+
|
|
263
|
+
// Check parts for numeric
|
|
264
|
+
if( isNaN(year) || isNaN(month) || isNaN(day) || isNaN(hour) || isNaN(minute) || isNaN(second) ) {
|
|
265
|
+
throw new Error("minitz: Could not parse ISO8601 string.");
|
|
266
|
+
} else {
|
|
267
|
+
// Check generated date
|
|
268
|
+
const generatedDate = new Date(Date.UTC(year, month-1, day, hour, minute, second));
|
|
269
|
+
if (!(year == generatedDate.getUTCFullYear()
|
|
270
|
+
&& month == generatedDate.getUTCMonth()+1
|
|
271
|
+
&& day == generatedDate.getUTCDate()
|
|
272
|
+
&& hour == generatedDate.getUTCHours()
|
|
273
|
+
&& minute == generatedDate.getUTCMinutes()
|
|
274
|
+
&& second == generatedDate.getUTCSeconds())) {
|
|
275
|
+
throw new Error("minitz: ISO8601 string contains invalid date or time");
|
|
276
|
+
}
|
|
277
|
+
// Check for UTC flag
|
|
278
|
+
if ((dateTimeString.indexOf("Z") > 0)) {
|
|
279
|
+
// Handle date as UTC time, ignoring input timezone
|
|
280
|
+
return minitz.tp(year, month, day, hour, minute, second, "Etc/UTC");
|
|
281
|
+
} else {
|
|
282
|
+
// Handle date as local time, and convert from specified time zone
|
|
283
|
+
// Note: Date already validated by the UTC-parsing
|
|
284
|
+
return minitz.tp(year, month, day, hour, minute, second, timezone);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
114
289
|
minitz.minitz = minitz;
|
|
115
290
|
|
|
116
291
|
/**
|
|
@@ -123,7 +298,7 @@
|
|
|
123
298
|
* @property {string | Date} [startAt] - When to start running
|
|
124
299
|
* @property {string | Date} [stopAt] - When to stop running
|
|
125
300
|
* @property {string} [timezone] - Time zone in Europe/Stockholm format
|
|
126
|
-
* @property {boolean} [legacyMode] - Combine day-of-month and day-of-week using OR. Default is
|
|
301
|
+
* @property {boolean} [legacyMode] - Combine day-of-month and day-of-week using true = OR, false = AND. Default is OR.
|
|
127
302
|
* @property {?} [context] - Used to pass any object to scheduled function
|
|
128
303
|
*/
|
|
129
304
|
|
|
@@ -142,7 +317,7 @@
|
|
|
142
317
|
}
|
|
143
318
|
|
|
144
319
|
// Keep options, or set defaults
|
|
145
|
-
options.legacyMode = (options.legacyMode === void 0) ?
|
|
320
|
+
options.legacyMode = (options.legacyMode === void 0) ? true : options.legacyMode;
|
|
146
321
|
options.paused = (options.paused === void 0) ? false : options.paused;
|
|
147
322
|
options.maxRuns = (options.maxRuns === void 0) ? Infinity : options.maxRuns;
|
|
148
323
|
options.catch = (options.catch === void 0) ? false : options.catch;
|
|
@@ -203,21 +378,19 @@
|
|
|
203
378
|
* Sets internals using a Date
|
|
204
379
|
* @private
|
|
205
380
|
*
|
|
206
|
-
* @param {Date} date - Input date
|
|
381
|
+
* @param {Date} date - Input date in local time
|
|
207
382
|
*/
|
|
208
|
-
CronDate.prototype.fromDate = function (
|
|
383
|
+
CronDate.prototype.fromDate = function (inputDate) {
|
|
209
384
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
this.
|
|
215
|
-
this.
|
|
216
|
-
this.
|
|
217
|
-
this.
|
|
218
|
-
this.
|
|
219
|
-
this.months = date.getMonth();
|
|
220
|
-
this.years = date.getFullYear();
|
|
385
|
+
const date = minitz.toTZ(inputDate, this.timezone);
|
|
386
|
+
|
|
387
|
+
this.milliseconds = inputDate.getMilliseconds();
|
|
388
|
+
this.seconds = date.second;
|
|
389
|
+
this.minutes = date.minute;
|
|
390
|
+
this.hours = date.hour;
|
|
391
|
+
this.days = date.day;
|
|
392
|
+
this.months = date.month - 1;
|
|
393
|
+
this.years = date.year;
|
|
221
394
|
|
|
222
395
|
};
|
|
223
396
|
|
|
@@ -245,15 +418,15 @@
|
|
|
245
418
|
* @param {Date} date - Input date
|
|
246
419
|
*/
|
|
247
420
|
CronDate.prototype.apply = function () {
|
|
248
|
-
const newDate = new Date(this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.milliseconds);
|
|
421
|
+
const newDate = new Date(Date.UTC(this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.milliseconds));
|
|
249
422
|
|
|
250
|
-
this.milliseconds = newDate.
|
|
251
|
-
this.seconds = newDate.
|
|
252
|
-
this.minutes = newDate.
|
|
253
|
-
this.hours = newDate.
|
|
254
|
-
this.days = newDate.
|
|
255
|
-
this.months = newDate.
|
|
256
|
-
this.years = newDate.
|
|
423
|
+
this.milliseconds = newDate.getUTCMilliseconds();
|
|
424
|
+
this.seconds = newDate.getUTCSeconds();
|
|
425
|
+
this.minutes = newDate.getUTCMinutes();
|
|
426
|
+
this.hours = newDate.getUTCHours();
|
|
427
|
+
this.days = newDate.getUTCDate();
|
|
428
|
+
this.months = newDate.getUTCMonth();
|
|
429
|
+
this.years = newDate.getUTCFullYear();
|
|
257
430
|
};
|
|
258
431
|
|
|
259
432
|
/**
|
|
@@ -263,15 +436,7 @@
|
|
|
263
436
|
* @param {Date} date - Input date
|
|
264
437
|
*/
|
|
265
438
|
CronDate.prototype.fromString = function (str) {
|
|
266
|
-
|
|
267
|
-
const parsedDate = this.parseISOLocal(str);
|
|
268
|
-
|
|
269
|
-
// Throw if we did get an invalid date
|
|
270
|
-
if( isNaN(parsedDate) ) {
|
|
271
|
-
throw new TypeError("CronDate: Provided string value for CronDate could not be parsed as date.");
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
this.fromDate(parsedDate);
|
|
439
|
+
return this.fromDate(minitz.fromTZISO(str, this.timezone));
|
|
275
440
|
};
|
|
276
441
|
|
|
277
442
|
/**
|
|
@@ -451,11 +616,10 @@
|
|
|
451
616
|
* @returns {Date}
|
|
452
617
|
*/
|
|
453
618
|
CronDate.prototype.getDate = function (internal) {
|
|
454
|
-
const targetDate = new Date(this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.milliseconds);
|
|
455
619
|
if (internal || !this.timezone) {
|
|
456
|
-
return
|
|
620
|
+
return new Date(this.years, this.months, this.days, this.hours, this.minutes, this.seconds, this.milliseconds);
|
|
457
621
|
} else {
|
|
458
|
-
return minitz.
|
|
622
|
+
return minitz(this.years, this.months+1, this.days, this.hours, this.minutes, this.seconds, this.timezone);
|
|
459
623
|
}
|
|
460
624
|
};
|
|
461
625
|
|
|
@@ -463,78 +627,10 @@
|
|
|
463
627
|
* Convert current state back to a javascript Date() and return UTC milliseconds
|
|
464
628
|
* @public
|
|
465
629
|
*
|
|
466
|
-
* @param {boolean} internal - If this is an internal call
|
|
467
630
|
* @returns {Date}
|
|
468
631
|
*/
|
|
469
|
-
CronDate.prototype.getTime = function (
|
|
470
|
-
return this.getDate(
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Takes a iso 8001 local date time string and creates a Date object
|
|
475
|
-
* @private
|
|
476
|
-
*
|
|
477
|
-
* @param {string} dateTimeString - an ISO 8001 format date and time string
|
|
478
|
-
* with all components, e.g. 2015-11-24T19:40:00
|
|
479
|
-
* @returns {Date|number} - Date instance from parsing the string. May be NaN.
|
|
480
|
-
*/
|
|
481
|
-
CronDate.prototype.parseISOLocal = function (dateTimeString) {
|
|
482
|
-
const dateTimeStringSplit = dateTimeString.split(/\D/);
|
|
483
|
-
|
|
484
|
-
// Check for completeness
|
|
485
|
-
if (dateTimeStringSplit.length < 6) {
|
|
486
|
-
return NaN;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const
|
|
490
|
-
year = parseInt(dateTimeStringSplit[0], 10),
|
|
491
|
-
month = parseInt(dateTimeStringSplit[1], 10),
|
|
492
|
-
day = parseInt(dateTimeStringSplit[2], 10),
|
|
493
|
-
hour = parseInt(dateTimeStringSplit[3], 10),
|
|
494
|
-
minute = parseInt(dateTimeStringSplit[4], 10),
|
|
495
|
-
second = parseInt(dateTimeStringSplit[5], 10);
|
|
496
|
-
|
|
497
|
-
// Check parts for numeric
|
|
498
|
-
if( isNaN(year) || isNaN(month) || isNaN(day) || isNaN(hour) || isNaN(minute) || isNaN(second) ) {
|
|
499
|
-
return NaN;
|
|
500
|
-
} else {
|
|
501
|
-
let generatedDate;
|
|
502
|
-
|
|
503
|
-
// Check for UTC flag
|
|
504
|
-
if ((dateTimeString.indexOf("Z") > 0)) {
|
|
505
|
-
|
|
506
|
-
// Handle date as UTC
|
|
507
|
-
generatedDate = new Date(Date.UTC(year, month-1, day, hour, minute, second));
|
|
508
|
-
|
|
509
|
-
// Check generated date
|
|
510
|
-
if (year == generatedDate.getUTCFullYear()
|
|
511
|
-
&& month == generatedDate.getUTCMonth()+1
|
|
512
|
-
&& day == generatedDate.getUTCDate()
|
|
513
|
-
&& hour == generatedDate.getUTCHours()
|
|
514
|
-
&& minute == generatedDate.getUTCMinutes()
|
|
515
|
-
&& second == generatedDate.getUTCSeconds()) {
|
|
516
|
-
return generatedDate;
|
|
517
|
-
} else {
|
|
518
|
-
return NaN;
|
|
519
|
-
}
|
|
520
|
-
} else {
|
|
521
|
-
|
|
522
|
-
// Handle date as local time
|
|
523
|
-
generatedDate = new Date(year, month-1, day, hour, minute, second);
|
|
524
|
-
|
|
525
|
-
// Check generated date
|
|
526
|
-
if (year == generatedDate.getFullYear()
|
|
527
|
-
&& month == generatedDate.getMonth()+1
|
|
528
|
-
&& day == generatedDate.getDate()
|
|
529
|
-
&& hour == generatedDate.getHours()
|
|
530
|
-
&& minute == generatedDate.getMinutes()
|
|
531
|
-
&& second == generatedDate.getSeconds()) {
|
|
532
|
-
return generatedDate;
|
|
533
|
-
} else {
|
|
534
|
-
return NaN;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
}
|
|
632
|
+
CronDate.prototype.getTime = function () {
|
|
633
|
+
return this.getDate().getTime();
|
|
538
634
|
};
|
|
539
635
|
|
|
540
636
|
/**
|
|
@@ -1201,9 +1297,9 @@
|
|
|
1201
1297
|
|
|
1202
1298
|
// Ensure previous run is a CronDate
|
|
1203
1299
|
prev = new CronDate(prev, this.options.timezone);
|
|
1204
|
-
|
|
1300
|
+
|
|
1205
1301
|
// Previous run should never be before startAt
|
|
1206
|
-
if( this.options.startAt && prev && prev.getTime(
|
|
1302
|
+
if( this.options.startAt && prev && prev.getTime() < this.options.startAt.getTime() ) {
|
|
1207
1303
|
prev = this.options.startAt;
|
|
1208
1304
|
}
|
|
1209
1305
|
|
|
@@ -1211,13 +1307,13 @@
|
|
|
1211
1307
|
const
|
|
1212
1308
|
nextRun = this.once || new CronDate(prev, this.options.timezone).increment(this.pattern, this.options, hasPreviousRun);
|
|
1213
1309
|
|
|
1214
|
-
if (this.once && this.once.getTime(
|
|
1310
|
+
if (this.once && this.once.getTime() <= prev.getTime()) {
|
|
1215
1311
|
return null;
|
|
1216
1312
|
|
|
1217
1313
|
} else if ((nextRun === null) ||
|
|
1218
1314
|
(this.options.maxRuns <= 0) ||
|
|
1219
1315
|
(this.options.kill) ||
|
|
1220
|
-
(this.options.stopAt && nextRun.getTime(
|
|
1316
|
+
(this.options.stopAt && nextRun.getTime() >= this.options.stopAt.getTime() )) {
|
|
1221
1317
|
return null;
|
|
1222
1318
|
|
|
1223
1319
|
} else {
|