Node.js library for parsing crontab instructions
A JavaScript library for parsing and manipulating cron expressions. Features timezone support, DST handling, and iterator capabilities.
npm install cron-parser
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └─ day of week (0-7, 1L-7L) (0 or 7 is Sun)
│ │ │ │ └────── month (1-12, JAN-DEC)
│ │ │ └─────────── day of month (1-31, L)
│ │ └──────────────── hour (0-23)
│ └───────────────────── minute (0-59)
└────────────────────────── second (0-59, optional)
*
Any value
* * * * * (every minute)
?
Any value (alias for *)
? * * * * (every minute)
,
Value list separator
1,2,3 * * * * (1st, 2nd, and 3rd minute)
-
Range of values
1-5 * * * * (every minute from 1 through 5)
/
Step values
*/5 * * * * (every 5th minute)
L
Last day of month/week
0 0 L * * (midnight on last day of month)
#
Nth day of month
0 0 * * 1#1 (first Monday of month)
H
Randomized value
H * * * * (every n minute where n is randomly picked within [0, 59])
@yearly
Once a year at midnight of January 1
0 0 0 1 1 *
@monthly
Once a month at midnight of first day
0 0 0 1 * *
@weekly
Once a week at midnight on Sunday
0 0 0 * * 0
@daily
Once a day at midnight
0 0 0 * * *
@hourly
Once an hour at the beginning of the hour
0 0 * * * *
@minutely
Once a minute
0 * * * * *
@secondly
Once a second
* * * * * *
@weekdays
Every weekday at midnight
0 0 0 * * 1-5
@weekends
Every weekend at midnight
0 0 0 * * 0,6
* ? , - / H
minute
0-59
* ? , - / H
hour
0-23
* ? , - / H
day of month
1-31
* ? , - / H L
month
1-12
* ? , - / H
JAN-DEC
day of week
0-7
* ? , - / H L #
SUN-SAT (0 or 7 is Sunday)
H special character
strict
boolean
Enable strict mode validation
When using string dates, the following formats are supported:
import { CronExpressionParser } from 'cron-parser';
try {
const interval = CronExpressionParser.parse('*/2 * * * *');
// Get next date
console.log('Next:', interval.next().toString());
// Get next 3 dates
console.log(
'Next 3:',
interval.take(3).map((date) => date.toString()),
);
// Get previous date
console.log('Previous:', interval.prev().toString());
} catch (err) {
console.log('Error:', err.message);
}
import { CronExpressionParser } from 'cron-parser';
const options = {
currentDate: '2023-01-01T00:00:00Z',
endDate: '2024-01-01T00:00:00Z',
tz: 'Europe/London',
};
try {
const interval = CronExpressionParser.parse('0 0 * * *', options);
console.log('Next:', interval.next().toString());
} catch (err) {
console.log('Error:', err.message);
}
The library provides handling of date ranges with automatic adjustment of the currentDate:
startDate as fallback: If currentDate is not provided but startDate is, the startDate will be used as the currentDate.
const options = {
startDate: '2023-01-01T00:00:00Z', // No currentDate provided
};
// currentDate will be set to 2023-01-01T00:00:00Z automatically
const interval = CronExpressionParser.parse('0 0 * * *', options);
Automatic clamping: If currentDate is outside the bounds defined by startDate and endDate, it will be automatically adjusted:
const options = {
currentDate: '2022-01-01T00:00:00Z', // Before startDate
startDate: '2023-01-01T00:00:00Z',
endDate: '2024-01-01T00:00:00Z',
};
// currentDate will be clamped to startDate (2023-01-01T00:00:00Z)
const interval = CronExpressionParser.parse('0 0 * * *', options);
Validation during iteration: While the initial currentDate is automatically adjusted, the library still validates date bounds during iteration:
const options = {
currentDate: '2023-12-31T00:00:00Z',
endDate: '2024-01-01T00:00:00Z', // Very close end date
};
const interval = CronExpressionParser.parse('0 0 * * *', options);
console.log('Next:', interval.next().toString()); // Works fine
// This will throw an error because it would exceed endDate
try {
console.log('Next:', interval.next().toString());
} catch (err) {
console.log('Error:', err.message); // "Out of the time span range"
}
This behavior simplifies working with date ranges by removing the need to manually ensure that currentDate is within bounds, reducing confusion and making the API more intuitive.
For working with crontab files, use the CronFileParser:
…
In several implementations of CRON, it's ambiguous to specify both the Day Of Month and Day Of Week parameters simultaneously, as it's unclear which one should take precedence. Despite this ambiguity, this library allows both parameters to be set by default, although the resultant behavior might not align with your expectations.
To resolve this ambiguity, you can activate the strict mode of the library. When strict mode is enabled, the library enforces several validation rules:
H(0-5) in day of month, or a step wider than the range it applies to, such as H(1-5)/10 (see Hash support)These validations help ensure that your cron expressions are unambiguous and correctly formatted.
…
The library supports parsing the range 0L - 7L in the weekday position of the cron expression, where the L means "last occurrence of this weekday for the month in progress".
For example, the following expression will run on the last Monday of the month at midnight:
import { CronExpressionParser } from 'cron-parser';
// Last Monday of every month at midnight
const lastMonday = CronExpressionParser.parse('0 0 0 * * 1L');
// You can also combine L expressions with other weekday expressions
// This will run every Monday and the last Wednesday of the month
const mixedWeekdays = CronExpressionParser.parse('0 0 0 * * 1,3L');
// Last day of every month
const lastDay = CronExpressionParser.parse('0 0 L * *');
import { CronExpressionParser } from 'cron-parser';
const interval = CronExpressionParser.parse('0 */2 * * *');
// Using for...of
for (const date of interval) {
console.log('Iterator value:', date.toString());
if (someCondition) break;
}
// Using take() for a specific number of iterations
const nextFiveDates = interval.take(5);
console.log(
'Next 5 dates:',
nextFiveDates.map((date) => date.toString()),
);
The library provides robust timezone support using Luxon, handling DST transitions correctly:
import { CronExpressionParser } from 'cron-parser';
const options = {
currentDate: '2023-03-26T01:00:00',
tz: 'Europe/London',
};
const interval = CronExpressionParser.parse('0 * * * *', options);
// Will correctly handle DST transition
console.log('Next dates during DST transition:');
console.log(interval.next().toString());
console.log(interval.next().toString());
console.log(interval.next().toString());
You can modify cron fields programmatically using CronFieldCollection.from and construct a new expression:
…
The CronFieldCollection.from method accepts either CronField instances or raw values that would be valid for creating new CronField instances. This is particularly useful when you need to modify only specific fields while keeping others unchanged.
The library supports adding jitter to the returned intervals using the H special character in a field. When H is specified instead of *, a random value is used (H is replaced by 23, where 23 is picked randomly, within the valid range of the field).
This jitter allows to spread the load when it comes to job scheduling. This feature is inspired by Jenkins's cron syntax.
…
A step only produces several occurrences while it is narrow enough to fit the range more than once. When the step is wider than the range - as in H(1-5)/10, or H/60 in a field whose constraints are narrower than 60 - no step-aligned value is guaranteed to land inside the range, so the field falls back to a single random occurrence within it, exactly as H(1-5) wou
prev() wrongly skipping back an extra day on first call in specific case of time change
[Feature Request] It would be nice to support last x days, e.g. '0 0 0 L-3 * *' (3 days to the end of every month)
Optionally disable cron extensions
currentDate is not included in timespan range
Request for `LW` (Last Weekday) in dayOfMonth
Any plans to add support for L and W characters?
expression has inconsistent behaviour for time ranges that span Daylight Saving Time change
Stringify, possible stepped range improvements
Adding a "this()" function?