What is croner?
The croner npm package is a high-performance task scheduler for Node.js that allows you to run tasks at specific times or intervals. It is designed to be a drop-in replacement for the 'cron' package with additional features and improvements.
What are croner's main functionalities?
Simple cron job scheduling
This feature allows you to schedule a task to run at intervals defined by the cron syntax. In the provided code sample, a job is scheduled to run every 5 seconds.
const { Cron } = require('croner');
const job = Cron('*/5 * * * * *', () => {
console.log('This will run every 5 seconds');
});
One-time execution
This feature allows you to schedule a task to run once at a specific time in the future. The code sample schedules a job to run once after 10 seconds.
const { Cron } = require('croner');
const job = Cron(new Date(Date.now() + 10000), () => {
console.log('This will run once after 10 seconds');
});
Stopping a job
This feature allows you to stop a scheduled job. In the code sample, a job is scheduled to run every 5 seconds but is stopped after 15 seconds.
const { Cron } = require('croner');
const job = Cron('*/5 * * * * *', () => {
console.log('This job will be stopped.');
});
setTimeout(() => {
job.stop();
}, 15000);
Timezone support
This feature allows you to schedule jobs according to a specific timezone. The code sample schedules a job to run at 10:30 AM in the 'America/New_York' timezone.
const { Cron } = require('croner');
const job = Cron('0 30 10 * * *', () => {
console.log('This will run at 10:30 AM in the America/New_York timezone.');
}, { timezone: 'America/New_York' });
Other packages similar to croner
node-schedule
node-schedule is a flexible cron-like and not-cron-like job scheduler for Node.js. It allows you to schedule jobs using both cron-style and human-readable syntax. It is similar to croner but offers a different API and additional scheduling features like scheduling jobs with JavaScript Date objects.
agenda
agenda is a job scheduling library for Node.js that uses MongoDB for persisting job data. It is more suitable for distributed or long-running job tasks. Unlike croner, which focuses on in-memory cron job scheduling, agenda provides persistence and is better suited for applications that require job recovery and failover capabilities.
bull
bull is a Redis-based queue system for Node.js. It is designed for handling distributed jobs and messages in Node.js applications. While croner is used for scheduling tasks, bull is more focused on job queuing, processing, and concurrency, making it suitable for more complex job handling scenarios.
Trigger functions or evaluate cron expressions in JavaScript or TypeScript. No dependencies. All features. Node. Deno. Bun. Browser.
Try it live on jsfiddle, and check out the full documentation on croner.56k.guru.
Croner - Cron for JavaScript and TypeScript
- Trigger functions in JavaScript using Cron syntax.
- Evaluate cron expressions and get a list of upcoming run times.
- Uses Vixie-cron pattern, with additional features such as
L
for last day and weekday of month and #
for nth weekday of month. - Works in Node.js >=7.6 (both require and import), Deno >=1.16 and Bun >=0.2.2.
- Works in browsers as standalone, UMD or ES-module.
- Target different time zones.
- Built-in overrun protection
- Built-in error handling
- Includes TypeScript typings.
- Support for asynchronous functions.
- Pause, resume, or stop execution after a task is scheduled.
- Operates in-memory, with no need for a database or configuration files.
- Zero dependencies.
Quick examples:
const job = Cron('*/5 * * * * *', () => {
console.log('This will run every fifth second');
});
const nextSundays = Cron('0 0 0 * * 7').nextRuns(100);
console.log(nextSundays);
const msLeft = Cron('59 59 23 24 DEC *').nextRun() - new Date();
console.log(Math.floor(msLeft/1000/3600/24) + " days left to next christmas eve");
Cron('2024-01-23T00:00:00', { timezone: 'Asia/Kolkata' }, () => { console.log('Yay!') });
More examples...
Installation
Full documentation on installation and usage is found at https://croner.56k.guru
Note
If you are migrating from a different library such as cron
or node-cron
, or upgrading from a older version of croner, see the migration section of the manual.
Install croner using your favorite package manager or CDN. then include it in you project:
Using Node.js or Bun
import { Cron } from "croner";
const { Cron } = require("croner");
Using Deno
import { Cron } from "https://deno.land/x/croner@6.0.3/dist/croner.js";
In a webpage using the UMD-module
<script src="https://cdn.jsdelivr.net/npm/croner@6/dist/croner.umd.min.js"></script>
Documentation
Signature
Cron takes three arguments
const job = Cron("* * * * * *", { maxRuns: 1 }, () => {} );
job.schedule(job, context) => {});
The job will be sceduled to run at next matching time unless you supply option { paused: true }
. The Cron(...)
constructor will return a Cron instance, later called job
, which have a couple of methods and properties listed below.
Status
job.nextRun( startFromDate );
job.nextRuns(10, startFromDate );
job.msToNext( startFromDate );
job.currentRun();
job.previousRun( );
job.isRunning();
job.isStopped();
job.isBusy();
job.getPattern();
Control functions
job.trigger();
job.pause();
job.resume();
job.stop();
Properties
job.name
Options
Key | Default value | Data type | Remarks |
---|
name | undefined | String | If you specify a name for the job, Croner will keep a reference to the job in the exported array scheduledJobs . The reference will be removed on .stop() . |
maxRuns | Infinite | Number | |
catch | false | Boolean|Function | Catch unhandled errors in triggered function. Passing true will silently ignore errors. Passing a callback function will trigger this callback on error. |
timezone | undefined | String | Timezone in Europe/Stockholm format |
startAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00) in local time (according to timezone parameter if passed) |
stopAt | undefined | String | ISO 8601 formatted datetime (2021-10-17T23:43:00) in local time (according to timezone parameter if passed) |
interval | 0 | Number | Minimum number of seconds between triggers. |
paused | false | Boolean | If the job should be paused from start. |
context | undefined | Any | Passed as the second parameter to triggered function |
legacyMode | true | boolean | Combine day-of-month and day-of-week using true = OR, false = AND |
unref | false | boolean | Setting this to true unrefs the internal timer, which allows the process to exit even if a cron job is running. |
utcOffset | undefined | number | Schedule using a specific utc offset in minutes. This does not take care of daylight savings time, you probably want to use option timezone instead. |
protect | undefined | boolean|Function | Enabled over-run protection. Will block new triggers as long as an old trigger is in progress. Pass either true or a callback function to enable |
Warning
Unreferencing timers (option unref
) is only supported by Node.js and Deno.
Browsers have not yet implemented this feature, and it does not make sense to use it in a browser environment.
Pattern
The expressions used by Croner are very similar to those of Vixie Cron, but with a few additions and changes as outlined below:
-
Croner expressions have the following additional modifiers:
- ?: The question mark is substituted with the time of initialization. For example, ? ? * * * * would be substituted with 25 8 * * * * if the time is :08:25 at the time of new Cron('? ? * * * *', <...>). The question mark can be used in any field.
- L: The letter 'L' can be used in the day of the month field to indicate the last day of the month. When used in the day of the week field in conjunction with the # character, it denotes the last specific weekday of the month. For example,
5#L
represents the last Friday of the month. - #: The # character specifies the "nth" occurrence of a particular day within a month. For example, supplying
5#2
in the day of week field signifies the second Friday of the month. This can be combined with ranges and supports day names. For instance, MON-FRI#2 would match the Monday through Friday of the second week of the month.
-
Croner allows you to pass a JavaScript Date object or an ISO 8601 formatted string as a pattern. The scheduled function will trigger at the specified date/time and only once. If you use a timezone different from the local timezone, you should pass the ISO 8601 local time in the target location and specify the timezone using the options (2nd parameter).
-
Croner also allows you to change how the day-of-week and day-of-month conditions are combined. By default, Croner (and Vixie cron) will trigger when either the day-of-month OR the day-of-week conditions match. For example, 0 20 1 * MON
will trigger on the first of the month as well as each Monday. If you want to use AND (so that it only triggers on Mondays that are also the first of the month), you can pass { legacyMode: false }
. For more information, see issue #53.
Field | Required | Allowed values | Allowed special characters | Remarks |
---|
Seconds | Optional | 0-59 | * , - / ? | |
Minutes | Yes | 0-59 | * , - / ? | |
Hours | Yes | 0-23 | * , - / ? | |
Day of Month | Yes | 1-31 | * , - / ? L | |
Month | Yes | 1-12 or JAN-DEC | * , - / ? | |
Day of Week | Yes | 0-7 or SUN-MON | * , - / ? L # | 0 to 6 are Sunday to Saturday 7 is Sunday, the same as 0 # is used to specify nth occurrence of a weekday |
Note
Weekday and month names are case-insensitive. Both MON
and mon
work.
When using L
in the Day of Week field, it affects all specified weekdays. For example, L5,6
means the last Friday and Saturday in the month."
The # character can be used to specify the "nth" weekday of the month. For example, 5#2 represents the second Friday of the month.
It is also possible to use the following "nicknames" as pattern.
Nickname | Description |
---|
@yearly | Run once a year, ie. "0 0 1 1 *". |
@annually | Run once a year, ie. "0 0 1 1 *". |
@monthly | Run once a month, ie. "0 0 1 * *". |
@weekly | Run once a week, ie. "0 0 * * 0". |
@daily | Run once a day, ie. "0 0 * * *". |
@hourly | Run once an hour, ie. "0 * * * *". |
Why another JavaScript cron implementation
Because the existing ones are not good enough. They have serious bugs, use bloated dependencies, do not work in all environments, and/or simply do not work as expected.
| croner | cronosjs | node-cron | cron | node-schedule |
---|
Platforms | | | | | |
Node.js (CommonJS) | ✓ | ✓ | ✓ | ✓ | ✓ |
Browser (ESMCommonJS) | ✓ | ✓ | | | |
Deno (ESM) | ✓ | | | | |
Features | | | | | |
Over-run protection | ✓ | | | | |
Error handling | ✓ | | | | ✓ |
Typescript typings | ✓ | ✓ | | | |
Unref timers (optional) | ✓ | | | ✓ | |
dom-OR-dow | ✓ | ✓ | ✓ | ✓ | ✓ |
dom-AND-dow (optional) | ✓ | | | | |
Next run | ✓ | ✓ | | ✓ | ✓ |
Next n runs | ✓ | ✓ | | ✓ | |
Timezone | ✓ | ✓ | ✓ | ✓ | ✓ |
Minimum interval | ✓ | | | | |
Controls (stop/resume) | ✓ | ✓ | ✓ | ✓ | ✓ |
Range (0-13) | ✓ | ✓ | ✓ | ✓ | ✓ |
Stepping (*/5) | ✓ | ✓ | ✓ | ✓ | ✓ |
Last day of month (L) | ✓ | ✓ | | | |
Nth weekday of month (#) | ✓ | ✓ | | | |
In depth comparison of various libraries
| croner | cronosjs | node-cron | cron | node-schedule |
---|
Size | | | | | |
Minified size (KB) | 15.5 | 16.3 | 16.5 | - | - |
Bundlephobia minzip (KB) | 3.6 | 5.1 | 5.7 | 23.9 | 32.4 |
Dependencies | 0 | 0 | 1 | 1 | 3 |
Popularity | | | | | |
Downloads/week 1 | 576K | 31K | 433K | 2239K | 924K |
Quality | | | | | |
Issues 1 | 0 | 2 | 127 :warning: | 43 :warning: | 139 :warning: |
Code coverage | 99% | 98% | 100% | 81% | 94% |
Performance | | | | | |
Ops/s 1 2 3 4 5 6 | 99 952 | 49 308 | N/A :x: | Test failed :x: | 2 299 :warning: |
Ops/s 0 0 0 29 2 * | 65 392 | 17 138 | N/A :x: | Test failed :x: | 1 450 :warning: |
Tests | 8/8 | 7/8 | 0/8 2 :question: | 1/8 :warning: | 7/8 |
Test 0 0 23 * * * | 2022-10-09 00:40 | 2022-10-09 00:40 | N/A | 2022-10-09 00:40 | 2022-10-09 00:40 |
Test 0 0 0 L 2 * 3 | 2023-02-28 00:00 | 2023-02-28 00:00 | N/A | N/A | 2023-02-28 00:00 |
Test 0 0 0 29 2 * | 2024-02-29 00:00 | 2024-02-29 00:00 | N/A | 2023-03-29 00:00 :x: | 2024-02-29 00:00 |
Test 0 0 0 29 2 6 4 | 2048-02-09 00:00 | N/A | N/A | N/A | N/A |
Test 0 0 0 15 2 * | 2023-02-16 00:00 | 2023-02-16 00:00 | N/A | 2023-03-15 00:00 :x: | 2023-02-16 00:00 |
Test 0 0 0 * 10 1 | 2022-10-10 00:00 | 2022-10-10 00:00 | N/A | 2022-11-07 00:00 :x: | 2022-10-10 00:00 |
Test 0 0 23 31 3 * | 2023-03-31 23:00 | 2023-03-31 23:00 | N/A | 2023-04-01 23:00 :x: | 2023-03-31 23:00 |
Test 1 2 3 4 5 6 | 2023-05-04 03:02 | 2023-05-04 03:02 | N/A | 2023-06-03 03:02 :x: | 2023-05-04 03:02 |
Note
- Table last updated at 2022-10-23, issues and downloads updated 2023-02-19
- node-cron has no interface to predict when the function will run, so tests cannot be carried out.
- All tests and benchmarks were carried out using https://github.com/Hexagon/cron-comparison
Development
Master branch
This branch contains the latest stable code, released on npm's default channel latest
. You can install the latest stable revision by running the command below.
npm install croner --save
Dev branch
This branch contains code currently being tested, and is released at channel dev
on npm. You can install the latest revision of the development branch by running the command below.
npm install croner@dev
Warning
Expect breaking changes if you do not pin to a specific version.
A list of fixes and features currently released in the dev
branch is available here
Contributing & Support
Croner is founded and actively maintained by Hexagon. If you find value in Croner and want to contribute:
Your trust, support, and contributions drive the project. Every bit, irrespective of its size, is deeply appreciated.
License
MIT License