Croner

Trigger functions or evaluate cron expressions in JavaScript or TypeScript....

README

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 asL for last day and 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:

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

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

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

  12. // Run a function at a specific date/time using a non-local timezone (time is ISO 8601 local time)
  13. // This will run 2024-01-23 00:00:00 according to the time in Asia/Kolkata
  14. Cron('2024-01-23T00:00:00', { timezone: 'Asia/Kolkata' }, () => { console.log('Yay!') });

  15. ```

More examples...

Installation


Note

If you are migrating from a different library such as cron or node-cron, or upgrading from a older version of croner, see MIGRATION.md.


Install croner using your favorite package manager or CDN. then include it in you project:

Using Node.js or Bun

  1. ```javascript
  2. // ESM Import ...
  3. import { Cron } from "croner";

  4. // ... or CommonJS Require
  5. const Cron = require("croner");
  6. ```

Using Deno

  1. ```typescript
  2. import { Cron } from "https://deno.land/x/croner@6.0.3/dist/croner.js";
  3. ```

In a webpage using the UMD-module

  1. ```html
  2. <script src="https://cdn.jsdelivr.net/npm/croner@6/dist/croner.umd.min.js"></script>
  3. ```

Documentation


Signature


Cron takes three arguments

  options (optional)
  scheduleds function (optional)

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

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

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


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

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

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

Control functions


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

Properties


  1. ```javascript
  2. job.name    // Optional job name, populated if a name were passed to options
  3. ```

Options


KeyDefaultDataRemarks
|--------------|----------------|----------------|---------------------------------------|
nameundefinedStringIf
maxRunsInfiniteNumber|
catchfalseBoolean\|FunctionCatch
timezoneundefinedStringTimezone
startAtundefinedStringISO
stopAtundefinedStringISO
interval0NumberMinimum
pausedfalseBooleanIf
contextundefinedAnyPassed
legacyModetruebooleanCombine
unreffalsebooleanSetting
utcOffsetundefinednumberSchedule
protectundefinedboolean\|FunctionEnabled

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:

  1. ```javascript
  2. // ┌──────────────── (optional) second (0 - 59)
  3. // │ ┌────────────── minute (0 - 59)
  4. // │ │ ┌──────────── hour (0 - 23)
  5. // │ │ │ ┌────────── day of month (1 - 31)
  6. // │ │ │ │ ┌──────── month (1 - 12, JAN-DEC)
  7. // │ │ │ │ │ ┌────── day of week (0 - 6, SUN-Mon)
  8. // │ │ │ │ │ │       (0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0)
  9. // │ │ │ │ │ │
  10. // * * * * * *
  11. ```

  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: L can be used in the day of the month field to specify the last day of the month. It can also be used in the day of the week field to specify the last specific weekday of the month, for example, the last Friday.

  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.

FieldRequiredAllowedAllowedRemarks
|--------------|----------|----------------|----------------------------|---------------------------------------|
SecondsOptional0-59*|
MinutesYes0-59*|
HoursYes0-23*|
DayYes1-31*|
MonthYes1-12*|
DayYes0-7*0

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."



It is also possible to use the following "nicknames" as pattern.

NicknameDescription
-------------------
\@yearlyRun
\@annuallyRun
\@monthlyRun
\@weeklyRun
\@dailyRun
\@hourlyRun

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.

|cronosjsnode-croncronnode-schedule
|---------------------------|:-------------------:|:-------------------:|:---------:|:-------------------------:|:-------------------:|
**Platforms**
Node.js
Browser||
Deno||
**Features**
Over-run||
Error||
Typescript||
Unref||
dom-OR-dow
dom-AND-dow||
Next|
Next||
Timezone
Minimum||
Controls
Range
Stepping
Last||

In depth comparison of various libraries
  
|cronosjsnode-croncronnode-schedule
|---------------------------|:-------------------:|:-------------------:|:---------:|:-------------------------:|:-------------------:|
**Size**
Minified15.516.316.5-
Bundlephobia3.65.15.723.9
Dependencies0011
**Popularity**
Downloads/week576K31K433K2239K
**Quality**
Issues0212743
Code99%98%100%81%
**Performance**
Ops/s9949N/ATest
Ops/s6517N/ATest
**Tests****8/8****7/8****0/8****1/8**
Test2022-10-092022-10-09N/A2022-10-09
Test2023-02-282023-02-28N/AN/A
Test2024-02-292024-02-29N/A2023-03-29
Test2048-02-09N/AN/AN/A
Test2023-02-162023-02-16N/A2023-03-15
Test2022-10-102022-10-10N/A2022-11-07
Test2023-03-312023-03-31N/A2023-04-01
Test2023-05-042023-05-04N/A2023-06-03

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


[^1]: As of 2023-02-19
[^2]: Requires support for L-modifier
[^3]: In dom-AND-dow mode, only supported by croner at the moment.
[^4]: Node-cron has no way of showing next run time.


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.

  1. ```
  2. npm install croner --save
  3. ```

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.

  1. ```
  2. npm install croner@dev
  3. ```

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



... or ...

Buy Me a Coffee at ko-fi.com

License


MIT License