Home

Awesome

<p align="center"> <img src="https://cdn.jsdelivr.net/gh/hexagon/croner@master/croner.png" alt="Croner" width="150" height="150"><br> Trigger functions or evaluate cron expressions in JavaScript or TypeScript. No dependencies. All features. Node. Deno. Bun. Browser. <br><br>Try it live on <a href="https://jsfiddle.net/hexag0n/hoa8kwsb/">jsfiddle</a>, and check out the full documentation on <a href="https://croner.56k.guru">croner.56k.guru</a>.<br> </p>

Croner - Cron for JavaScript and TypeScript

npm version JSR NPM Downloads No dependencies MIT License

Quick examples:

// Basic: Run a function at the interval defined by a cron expression
const job = new Cron('*/5 * * * * *', () => {
	console.log('This will run every fifth second');
});

// Enumeration: What dates do the next 100 sundays occur on?
const nextSundays = new Cron('0 0 0 * * 7').nextRuns(100);
console.log(nextSundays);

// Days left to a specific date
const msLeft = new Cron('59 59 23 24 DEC *').nextRun() - new Date();
console.log(Math.floor(msLeft/1000/3600/24) + " days left to next christmas eve");

// Run a function at a specific date/time using a non-local timezone (time is ISO 8601 local time)
// This will run 2024-01-23 00:00:00 according to the time in Asia/Kolkata
new 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

// ESM Import ...
import { Cron } from "croner";

// ... or CommonJS Require, destructure to add type hints
const { Cron } = require("croner");

Using Deno

// From deno.land/x
import { Cron } from "https://deno.land/x/croner@8.1.2/dist/croner.js";

// ... or jsr.io
import { Cron } from "jsr:@hexagon/croner@8.1.2";

In a webpage using the UMD-module

<script src="https://cdn.jsdelivr.net/npm/croner@8/dist/croner.umd.min.js"></script>

Documentation

Signature

Cron takes three arguments

// Parameters
// - First: Cron pattern, js date object (fire once), or ISO 8601 time string (fire once)
// - Second: Options (optional)
// - Third: Function run trigger (optional)
const job = new Cron("* * * * * *", { maxRuns: 1 }, () => {} );

// If function is omitted in constructor, it can be scheduled later
job.schedule(job, /* optional */ context) => {});

The job will be sceduled to run at next matching time unless you supply option { paused: true }. The new Cron(...) constructor will return a Cron instance, later called job, which have a couple of methods and properties listed below.

Status

job.nextRun( /*optional*/ startFromDate );	// Get a Date object representing the next run.
job.nextRuns(10, /*optional*/ startFromDate ); // Get an array of Dates, containing the next n runs.
job.msToNext( /*optional*/ startFromDate ); // Get the milliseconds left until the next execution.
job.currentRun(); 		// Get a Date object showing when the current (or last) run was started.
job.previousRun( ); 		// Get a Date object showing when the previous job was started.

job.isRunning(); 	// Indicates if the job is scheduled and not paused or killed (true or false).
job.isStopped(); 	// Indicates if the job is permanently stopped using `stop()` (true or false).
job.isBusy(); 		// Indicates if the job is currently busy doing work (true or false).

job.getPattern(); 	// Returns the original pattern string

Control functions

job.trigger();		// Force a trigger instantly
job.pause();		// Pause trigger
job.resume();		// Resume trigger
job.stop();		// Stop the job completely. It is not possible to resume after this.
				// Note that this also removes named jobs from the exported `scheduledJobs` array.

Properties

job.name 			// Optional job name, populated if a name were passed to options

Options

KeyDefault valueData typeRemarks
nameundefinedStringIf 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().
maxRunsInfiniteNumber
catchfalseBoolean|FunctionCatch unhandled errors in triggered function. Passing true will silently ignore errors. Passing a callback function will trigger this callback on error.
timezoneundefinedStringTimezone in Europe/Stockholm format
startAtundefinedStringISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local time (according to timezone parameter if passed)
stopAtundefinedStringISO 8601 formatted datetime (2021-10-17T23:43:00)<br>in local time (according to timezone parameter if passed)
interval0NumberMinimum number of seconds between triggers.
pausedfalseBooleanIf the job should be paused from start.
contextundefinedAnyPassed as the second parameter to triggered function
legacyModetruebooleanCombine day-of-month and day-of-week using true = OR, false = AND
unreffalsebooleanSetting this to true unrefs the internal timer, which allows the process to exit even if a cron job is running.
utcOffsetundefinednumberSchedule using a specific utc offset in minutes. This does not take care of daylight savings time, you probably want to use option timezone instead.
protectundefinedboolean|FunctionEnabled 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:

// ┌──────────────── (optional) second (0 - 59)
// │ ┌────────────── minute (0 - 59)
// │ │ ┌──────────── hour (0 - 23)
// │ │ │ ┌────────── day of month (1 - 31)
// │ │ │ │ ┌──────── month (1 - 12, JAN-DEC)
// │ │ │ │ │ ┌────── day of week (0 - 6, SUN-Mon) 
// │ │ │ │ │ │       (0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0)
// │ │ │ │ │ │
// * * * * * *
FieldRequiredAllowed valuesAllowed special charactersRemarks
SecondsOptional0-59* , - / ?
MinutesYes0-59* , - / ?
HoursYes0-23* , - / ?
Day of MonthYes1-31* , - / ? L
MonthYes1-12 or JAN-DEC* , - / ?
Day of WeekYes0-7 or SUN-MON* , - / ? L #0 to 6 are Sunday to Saturday<br>7 is Sunday, the same as 0<br># 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, 5-6#L 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.

NicknameDescription
@yearlyRun once a year, ie. "0 0 1 1 *".
@annuallyRun once a year, ie. "0 0 1 1 *".
@monthlyRun once a month, ie. "0 0 1 * *".
@weeklyRun once a week, ie. "0 0 * * 0".
@dailyRun once a day, ie. "0 0 * * *".
@hourlyRun 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.

cronercronosjsnode-croncronnode-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 (#)
<details> <summary>In depth comparison of various libraries</summary>
cronercronosjsnode-croncronnode-schedule
Size
Minified size (KB)17.014.915.285.4 :warning:100.5 :warning:
Bundlephobia minzip (KB)5.05.15.725.829.2 :warning:
Dependencies00113 :warning:
Popularity
Downloads/week 12019K31K447K1366K1046K
Quality
Issues 102133 :warning:13145 :warning:
Code coverage99%98%100%81%94%
Performance
Ops/s 1 2 3 4 5 6160 65155 593N/A :x:6 313 :warning:2 726 :warning:
Ops/s 0 0 0 29 2 *176 71467 920N/A :x:3 104 :warning:737 :warning:
Tests11/1110/110/11 2 :question:7/11 :warning:9/11

Note

</details>

Development

Master branch

Node.js CI Deno CI Bun CI

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

Node.js CI Deno CI Bun CI

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

Footnotes

  1. As of 2023-10-10 2

  2. Node-cron has no way of showing next run time.