Skip to content

Commit 3181299

Browse files
Add support for @reboot special syntax (#350)
* Add support for @reboot special syntax - Added @reboot to the list of supported special expressions - Modified CronParser to handle @reboot special case - Updated ExpressionDescriptor to return "At system startup" for @reboot - Added tests for @reboot in both test files - Updated README to document @reboot support * Address review feedback: integrate @reboot with i18n and improve descriptions
1 parent 7ff2235 commit 3181299

File tree

7 files changed

+32
-4
lines changed

7 files changed

+32
-4
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This library was ported from the original C# implementation called [cron-express
1717
- Supports all cron expression special characters including * / , - ? L W, #
1818
- Supports 5, 6 (w/ seconds or year), or 7 (w/ seconds and year) part cron expressions
1919
- [Quartz Job Scheduler](http://www.quartz-scheduler.org/) cron expressions are supported
20+
- Supports time specification _nicknames_ (@yearly, @annually, @monthly, @weekly, @daily, @reboot)
2021
- i18n support with 30+ languages
2122

2223
## Demo
@@ -94,6 +95,9 @@ cronstrue.toString("* * * 6-8 *", { monthStartIndexZero: true });
9495
cronstrue.toString("@monthly");
9596
> "At 12:00 AM, on day 1 of the month"
9697

98+
cronstrue.toString("@reboot");
99+
> "Run once, at startup"
100+
97101
```
98102

99103
For more usage examples, including a demonstration of how cRonstrue can handle some very complex cron expressions, you can [reference the unit tests](https://github.com/bradymholt/cRonstrue/blob/main/test/cronstrue.ts).

src/cronParser.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ export class CronParser {
2929

3030
var expression = this.expression ?? '';
3131

32-
if (expression.startsWith('@')) {
32+
if (expression === "@reboot") {
33+
// Special handling for @reboot - create a marker array with a special format
34+
parsed = ["@reboot", "", "", "", "", "", ""];
35+
return parsed;
36+
} else if (expression.startsWith('@')) {
3337
var special = this.parseSpecial(this.expression);
3438
parsed = this.extractParts(special);
35-
3639
} else {
3740
parsed = this.extractParts(this.expression);
3841
}
@@ -51,7 +54,8 @@ export class CronParser {
5154
'@weekly': '0 0 * * 0',
5255
'@daily': '0 0 * * *',
5356
'@midnight': '0 0 * * *',
54-
'@hourly': '0 * * * *'
57+
'@hourly': '0 * * * *',
58+
'@reboot': '@reboot'
5559
};
5660

5761
const special = specialExpressions[expression];
@@ -328,7 +332,6 @@ export class CronParser {
328332
this.validateOnlyExpectedCharactersFound(parsed[6], standardCronPartCharacters);
329333

330334
this.validateAnyRanges(parsed);
331-
332335
}
333336

334337
protected validateAnyRanges(parsed: string[]) {

src/expressionDescriptor.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ export class ExpressionDescriptor {
104104
this.options.monthStartIndexZero
105105
);
106106
this.expressionParts = parser.parse();
107+
108+
// Special handling for @reboot
109+
if (this.expressionParts[0] === "@reboot") {
110+
return this.i18n.atReboot?.() || "Run once, at startup";
111+
}
112+
107113
var timeSegment = this.getTimeOfDayDescription();
108114
var dayOfMonthDesc = this.getDayOfMonthDescription();
109115
var monthDesc = this.getMonthDescription();

src/i18n/locale.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,5 @@ export interface Locale {
8080
* @return {string[]} months of year
8181
*/
8282
monthsOfTheYearInCase?(f?: number): string[];
83+
atReboot?(): string;
8384
}

src/i18n/locales/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,8 @@ export class en implements Locale {
176176
"December",
177177
];
178178
}
179+
180+
atReboot() {
181+
return "Run once, at startup";
182+
}
179183
}

test/cronParser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,11 @@ describe("CronParser", function () {
6161
it("should parse cron @ expression", function () {
6262
assert.equal(new CronParser("@weekly").parse().length, 7);
6363
});
64+
65+
it("should parse @reboot expression", function () {
66+
const parsedReboot = new CronParser("@reboot").parse();
67+
assert.equal(parsedReboot.length, 7);
68+
assert.equal(parsedReboot[0], "@reboot");
69+
});
6470
});
6571
});

test/cronstrue.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,10 @@ describe("Cronstrue", function () {
719719
it("@hourly", function () {
720720
assert.equal(cronstrue.toString(this.test?.title as string), "Every hour");
721721
});
722+
723+
it("@reboot", function () {
724+
assert.equal(cronstrue.toString(this.test?.title as string), "Run once, at startup");
725+
});
722726
});
723727

724728
describe("verbose", function () {

0 commit comments

Comments
 (0)