All Projects → Hexagon → croner

Hexagon / croner

Licence: MIT license
Trigger functions and/or evaluate cron expressions in JavaScript. No dependencies. Most features. All environments.

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Projects that are alternatives of or similar to croner

cron-schedule
A zero-dependency cron parser and scheduler for Node.js, Deno and the browser.
Stars: ✭ 28 (-83.43%)
Mutual labels:  cron, schedule, job, timer, deno
linda
Linda is a simple dispatcher library.
Stars: ✭ 12 (-92.9%)
Mutual labels:  task, cron, schedule, job, scheduler
Xxl Job
A distributed task scheduling framework.(分布式任务调度平台XXL-JOB)
Stars: ✭ 20,197 (+11850.89%)
Mutual labels:  task, schedule, job, scheduler
Go Quartz
Simple, zero-dependency scheduling library for Go
Stars: ✭ 118 (-30.18%)
Mutual labels:  cron, job, crontab, scheduler
delay-timer
Time-manager of delayed tasks. Like crontab, but synchronous asynchronous tasks are possible scheduling, and dynamic add/cancel/remove is supported.
Stars: ✭ 257 (+52.07%)
Mutual labels:  cron, schedule, crontab, scheduling
Ects
Elastic Crontab System 简单易用的分布式定时任务管理系统
Stars: ✭ 156 (-7.69%)
Mutual labels:  task, crontab, timer, scheduler
Bree
🚥 The best job scheduler for Node.js and JavaScript with cron, dates, ms, later, and human-friendly support. Works in Node v10+ and browsers, uses workers to spawn sandboxed processes, and supports async/await, retries, throttling, concurrency, and graceful shutdown. Simple, fast, and lightweight. Made for @ForwardEmail and @ladjs.
Stars: ✭ 933 (+452.07%)
Mutual labels:  cron, job, crontab, scheduler
schedule-rs
An in-process scheduler for periodic jobs. Schedule lets you run Rust functions on a cron-like schedule.
Stars: ✭ 93 (-44.97%)
Mutual labels:  task, cron, schedule, job
Quantum Core
⌚ Cron-like job scheduler for Elixir
Stars: ✭ 1,905 (+1027.22%)
Mutual labels:  cron, crontab, scheduler
Forest
分布式任务调度平台,分布式,任务调度,schedule,scheduler
Stars: ✭ 231 (+36.69%)
Mutual labels:  cron, schedule, job
legacy-bottlerockets
Node.js high availability queue and scheduler for background job processing
Stars: ✭ 25 (-85.21%)
Mutual labels:  cron, schedule, job
Shardingsphere Elasticjob Cloud
Stars: ✭ 248 (+46.75%)
Mutual labels:  cron, job, scheduler
YACLib
Yet Another Concurrency Library
Stars: ✭ 193 (+14.2%)
Mutual labels:  task, job, scheduler
Scheduler
Task scheduler for Golang
Stars: ✭ 171 (+1.18%)
Mutual labels:  task, cron, scheduler
Cronscheduler.aspnetcore
Cron Scheduler for AspNetCore 2.x/3.x or DotNetCore 2.x/3.x Self-hosted
Stars: ✭ 100 (-40.83%)
Mutual labels:  cron, scheduler, scheduling
Crontab
Parse Cron Expressions, Compose Cron Expression Strings and Caluclate Execution Dates.
Stars: ✭ 62 (-63.31%)
Mutual labels:  cron, schedule, crontab
Cronicle
A simple, distributed task scheduler and runner with a web based UI.
Stars: ✭ 979 (+479.29%)
Mutual labels:  cron, crontab, scheduler
job-plus
Job Plus项目是基于SpringBoot+Vue的轻量级定时任务管理系统
Stars: ✭ 17 (-89.94%)
Mutual labels:  task, cron, job
timer.cljs
Scheduling async operations in Clojurescript
Stars: ✭ 22 (-86.98%)
Mutual labels:  task, timer, scheduling
Deno cron
A cron Job scheduler for Deno that allows you to write human readable cron syntax with tons of flexibility
Stars: ✭ 35 (-79.29%)
Mutual labels:  cron, crontab, scheduler

Croner
Trigger functions and/or evaluate cron expressions in JavaScript. No dependencies. Most features. Node. Deno. Bun. Browser.

Try it live on jsfiddle.

Croner

Node.js CI Deno CI Bun CI npm version Codacy Badge NPM Downloads No dependencies MIT License

  • Trigger functions in JavaScript using Cron syntax.
  • Find first date of next month, find date of next tuesday, etc.
  • Pause, resume or stop execution after a task is scheduled.
  • Works in Node.js >=6.0 (both require and import).
  • Works in Deno >=1.16.
  • Works in Bun >=0.2.2
  • Works in browsers as standalone, UMD or ES-module.
  • Works with both JavaScriptCore and V8.
  • Schedule using specific target timezones.
  • Includes TypeScript typings.

Quick examples:

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

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

// Days left to a specific date
const msLeft = Cron('59 59 23 24 DEC *').next() - 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 2023-01-23 00:00:00 according to the time in Asia/Kolkata
Cron('2023-01-23T00:00:00', { timezone: 'Asia/Kolkata' }, () => { console.log('Yay') });

More examples...

Why another javascript cron implementation

Because the existing ones aren't good enough. They have serious bugs, use bloated dependencies, do not work in all environments and/or simply don't work as expected.

croner cronosjs node-cron cron node-schedule
Platforms
Node.js (CommonJS)
Browser (ESMCommonJS)
Deno (ESM)
Features
Typescript typings
dom-AND-dow
dom-OR-dow
Next run
Next n runs
Timezone
Minimum interval
Controls (stop/resume)
Range (0-13)
Stepping (*/5)
Last day of month (L)
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 672K 30K 376K 1574K 804K
Quality
Issues 1 0 2 118 ⚠️ 119 ⚠️ 135 ⚠️
Code coverage 99% 98% 100% 81% 94%
Performance
Ops/s 1 2 3 4 5 6 99 952 49 308 N/A Test failed 2 299 ⚠️
Ops/s 0 0 0 29 2 * 65 392 17 138 N/A Test failed 1 450 ⚠️
Tests 8/8 7/8 0/8 2 1/8 ⚠️ 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 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 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 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 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 2023-05-04 03:02

Note

  • Table last updated at 2022-10-23
  • node-cron has no interface to predict when the function will run. So tests cannot be carried out.
  • All tests and benchmarks carried out using https://github.com/Hexagon/cron-comparison

Installation

Node.js

npm install croner --save

JavaScript

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

// ... or CommonJS Require
const Cron = require("croner");

TypeScript

Notes for TypeScript:

  • If using strict eslint-rules, specifically new-cap combined with no-new, you need to import and use lower case cron instead of { Cron }.
import { Cron } from "croner";

const job : Cron = new Cron("* * * * * *", () => {
	console.log("This will run every second.");
});

Bun

bun add croner

Note If you experience problems during install, try using bun add croner --backend=copyfile.

import Cron from "croner";

Deno

JavaScript

import Cron from "https://deno.land/x/[email protected]/src/croner.js";

Cron("* * * * * *", () => {
	console.log("This will run every second.");
});

TypeScript

import { Cron } from "https://deno.land/x/[email protected]/src/croner.js";

const _scheduler : Cron = new Cron("* * * * * *", () => {
	console.log("This will run every second.");
});

Browser

Manual

  • Download latest zipball
  • Unpack
  • Grab croner.min.js (UMD and standalone) or croner.min.mjs (ES-module) from the dist/ folder

CDN

To use as a UMD-module (stand alone, RequireJS etc.)

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

To use as a ES-module

<script type="module">
	import Cron from "https://cdn.jsdelivr.net/npm/croner@5/dist/croner.min.mjs";

	// ... see usage section ...
</script>

Documentation

Full documentation available at hexagon.github.io/croner.

The short version:

Signature

Cron takes three arguments

const job = Cron("* * * * * *" /* Or a date object, or ISO 8601 local time */ , /*optional*/ { maxRuns: 1 } , /*optional*/ () => {} );

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

// States
const nextRun = job.next( /*optional*/ previousRun );	// Get a Date object representing next run
const nextRuns = job.enumerate(10, /*optional*/ startFrom ); // Get a array of Dates, containing next 10 runs according to pattern
const prevRun = job.previous( );	
const msToNext = job.msToNext( /*optional*/ previousRun ); // Milliseconds left to next execution
const isRunning = job.running();

// Control scheduled execution
job.pause();				
job.resume();
job.stop();

Options

Key Default value Data type Remarks
maxRuns Infinite Number
catch false Boolean Catch and ignore unhandled errors in triggered function
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

Pattern

The expressions of Croner are very similar to the ones of Vixie Cron, with a few additions and changes listed below.

  • Croner expressions support the following additional modifiers

    • ? A question mark is substituted with croner initialization time, as an example - ? ? * * * * would be substituted with 25 8 * * * * if time is <any hour>: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 month field, to specify the last day of the month.
  • Croner allow you to pass a javascript Date object, or a 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 local, you should pass ISO 8601 local time in target location, and specify timezone using the options (2nd parameter).

  • Croner allow to change how day-of-week and day-of-month is combined. By default croner (and Vixie cron) will trigger when day-of-month OR day-of-week conditions match. As an example 0 20 1 * MON will trigger on the first of the month, as well as on each monday. If you want to use AND (and in this example only trigger on mondays that is also 1st of the month) you can pass { legacyMode: false }. See issue #53 for more information.

// ┌──────────────── (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)
// │ │ │ │ │ │
// * * * * * *
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 * , - / ? 0 to 6 are Sunday to Saturday
7 is Sunday, the same as 0

Note Weekday and month names are case insensitive. Both MON and mon works.

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

Examples

Expressions

// Run a function according to pattern
Cron('15-45/10 */5 1,2,3 ? JAN-MAR SAT', { legacyMode: false }, function () {
	console.log('This will run every tenth second between second 15-45');
	console.log('every fifth minute of hour 1,2 and 3 when day of month');
	console.log('is the same as when Cron started, every saturday in January to March.');
});

Interval

// Trigger on specific interval combined with cron expression
Cron('* * * 7-16 * MON-FRI', { interval: 90, legacyMode: false }, function () {
	console.log('This will trigger every 90th second at 7-16 on mondays to fridays.');
});

Find dates

// Find next month
const nextMonth = Cron("@monthly").next(),
	nextSunday = Cron("@weekly").next(),
	nextSat29feb = Cron("0 0 0 29 2 6", { legacyMode: false }).next(),
	nextSunLastOfMonth = Cron("0 0 0 L * 7", { legacyMode: false }).next();

console.log("First day of next month: " +  nextMonth.toLocaleDateString());
console.log("Next sunday: " +  nextSunday.toLocaleDateString());
console.log("Next saturday at 29th of february: " +  nextSat29feb.toLocaleDateString());  // 2048-02-29
console.log("Next month ending with a sunday: " +  nextSunLastOfMonth.toLocaleDateString()); 

With options

const job = Cron(
	'* * * * *', 
	{ 
		maxRuns: Infinity, 
		startAt: "2021-11-01T00:00:00", 
		stopAt: "2021-12-01T00:00:00",
		timezone: "Europe/Stockholm"
	},
	function() {
		console.log('This will run every minute, from 2021-11-01 to 2021-12-01 00:00:00');
	}
);

Job controls

const job = Cron('* * * * * *', (self) => {
	console.log('This will run every second. Pause on second 10. Resume on 15. And quit on 20.');
	console.log('Current second: ', new Date().getSeconds());
	console.log('Previous run: ' + self.previous());
	console.log('Next run: ' + self.next());
});

Cron('10 * * * * *', {maxRuns: 1}, () => job.pause());
Cron('15 * * * * *', {maxRuns: 1}, () => job.resume());
Cron('20 * * * * *', {maxRuns: 1}, () => job.stop());

Passing a context

const data = {
	what: "stuff"
};

Cron('* * * * * *', { context: data }, (_self, context) => {
	console.log('This will print stuff: ' + context.what);
});

Cron('*/5 * * * * *', { context: data }, (self, context) => {
	console.log('After this, other stuff will be printed instead');
	context.what = "other stuff";
	self.stop();
});

Fire on a specific date/time

// A javascript date, or a ISO 8601 local time string can be passed, to fire a function once. 
// Always specify which timezone the ISO 8601 time string has with the timezone option.
let job = Cron("2025-01-01T23:00:00",{timezone: "Europe/Stockholm"},() => {
	console.log('This will run at 2025-01-01 23:00:00 in timezone Europe/Stockholm');
});

if (job.next() === null) {
	// The job will not fire for some reason
} else {
	console.log("Job will fire at " + job.next());
}

Act at completion

// Start a job firing once each 5th second, run at most 3 times
const job = new Cron("0/5 * * * * *", { maxRuns: 3 }, (job) => {
    
    // Do work
    console.log('Job Running');

    // Is this the last execution?
    if (!job.next()) {
        console.log('Last execution');
    }

});
 
// Will there be no executions? 
// This would trigger if you change maxRuns to 0, or manage to compose 
// an impossible cron expression.
if (!job.next() && !job.previous()) {
    console.log('No executions scheduled');
}

Contributing

See Contribution Guide

License

MIT

Footnotes

  1. As of 2022-10-08 2

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

  3. Requires support for L-modifier

  4. In dom-AND-dow mode, only supported by croner at the moment.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].