npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jondotsoy/cron

v0.6.3

Published

Cron expression parser and scheduler that generates execution times based on cron syntax

Readme

Cron

Cron expression parser and scheduler that generates execution times based on cron syntax.

Features

  • Full cron syntax support with 5 or 6 fields
  • Special expressions (@yearly, @monthly, @weekly, @daily, @hourly)
  • Month and day names support
  • Iterator-based API for generating execution times
  • Built-in scheduler with setInterval
  • Human-readable cron expression formatting with i18n support
  • TypeScript support with full type definitions

Installation

npm install @jondotsoy/cron
# or
bun install @jondotsoy/cron

Usage

Basic Usage

import { Cron } from "@jondotsoy/cron";

// Create a cron instance with an expression
const cron = new Cron("0 22 * * 1-5");

// Iterate over the next execution times
let count = 0;
for (const datetime of cron) {
  console.log(datetime.toString());
  // Break after getting the first 5 occurrences
  if (count++ >= 4) break;
}

Get Next Execution Time

import { Cron } from "@jondotsoy/cron";

const cron = new Cron("0 9 * * MON-FRI");
const nextExecution = Cron.next(cron);
console.log(`Next execution: ${nextExecution.toString()}`);

Schedule with setInterval

import { Cron } from "@jondotsoy/cron";

const cron = new Cron("*/5 * * * *"); // Every 5 minutes

const { promise, abort } = Cron.setInterval(() => {
  console.log("Task executed at:", new Date().toISOString());
}, cron);

// Stop the scheduler after some time
setTimeout(() => {
  abort();
  console.log("Scheduler stopped");
}, 60000);

// Wait for the scheduler to complete
await promise;

Using the using keyword (TypeScript 5.2+)

The setInterval return value supports the using keyword for automatic resource disposal:

import { Cron } from "@jondotsoy/cron";

{
  using cronInterval = Cron.setInterval(() => {
    console.log("Task executed at:", new Date().toISOString());
  }, new Cron("*/5 * * * *"));

  // The interval will automatically be aborted when exiting this scope
}
// Scheduler is automatically stopped here

Using the await using keyword (TypeScript 5.2+)

For async disposal that waits for the scheduler to fully complete:

import { Cron } from "@jondotsoy/cron";

{
  await using cronInterval = Cron.setInterval(() => {
    console.log("Task executed at:", new Date().toISOString());
  }, new Cron("@reboot")); // Executes once immediately

  // The interval will automatically be aborted and awaited when exiting this scope
}
// Scheduler is fully stopped and cleaned up here

Format Cron Expressions to Human-Readable Text

Convert cron expressions into natural language descriptions:

import { CronFormat } from "@jondotsoy/cron";

// Create a formatter with a locale
const formatter = new CronFormat("en");

// Format a cron expression
console.log(formatter.format("0 22 * * 1-5"));
// Output: "At 22:00 on every day-of-week from Monday through Friday."

console.log(formatter.format("*/5 * * * *"));
// Output: "At every 5th minute."

console.log(formatter.format("@weekly"));
// Output: "At 00:00 on Sunday."

Format to Parts for Custom Rendering

Get structured parts of the formatted expression for custom styling or rendering:

import { CronFormat } from "@jondotsoy/cron";

const formatter = new CronFormat("en");
const parts = formatter.formatToParts("0 22 * * 1-5");

// Returns an array of parts with type and value:
// [
//   { type: "literal", value: "At " },
//   { type: "hour", value: "22" },
//   { type: "literal", value: ":" },
//   { type: "minute", value: "00" },
//   { type: "literal", value: " " },
//   { type: "weekday", value: "on every day-of-week from Monday through Friday" },
//   { type: "literal", value: "." }
// ]

// Use parts for custom rendering (e.g., with colors or styles)
parts.forEach((part) => {
  if (part.type === "hour" || part.type === "minute") {
    console.log(`\x1b[36m${part.value}\x1b[0m`); // Cyan for time
  } else if (part.type === "weekday") {
    console.log(`\x1b[33m${part.value}\x1b[0m`); // Yellow for weekday
  } else {
    console.log(part.value);
  }
});

Internationalization Support

CronFormat supports multiple locales:

import { CronFormat } from "@jondotsoy/cron";

// English
const formatterEn = new CronFormat("en");
console.log(formatterEn.format("0 22 * * 1-5"));
// Output: "At 22:00 on every day-of-week from Monday through Friday."

// Spanish
const formatterEs = new CronFormat("es");
console.log(formatterEs.format("0 22 * * 1-5"));
// Output: "A las 22:00 cada día de la semana del lunes al viernes."

// Using Intl.Locale
const formatter = new CronFormat(new Intl.Locale("es"));
console.log(formatter.format("@daily"));
// Output: "A las 00:00."

Supported locales:

  • en - English
  • es - Spanish

Supported Cron Syntax

Standard Format

* * * * * [year]
│ │ │ │ │
│ │ │ │ └─── day of week (0-7, 0 and 7 are Sunday)
│ │ │ └───── month (1-12 or JAN-DEC)
│ │ └─────── day of month (1-31)
│ └───────── hour (0-23)
└─────────── minute (0-59)

The year field is optional.

Special Characters

  • * - Any value (matches all)
  • , - List separator (e.g., 1,3,5)
  • - - Range (e.g., 1-5)
  • / - Step values (e.g., */2 or 1-10/2)

Special Expressions

  • @yearly or @annually - Run once a year at midnight on January 1st
  • @monthly - Run once a month at midnight on the first day
  • @weekly - Run once a week at midnight on Sunday
  • @daily or @midnight - Run once a day at midnight
  • @hourly - Run once an hour at the beginning of the hour
  • @reboot - Run at startup (special case, not iterable)

Month Names

Months can be specified as numbers (1-12) or names (case-insensitive): JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC

Day Names

Days of week can be specified as numbers (0-7, where 0 and 7 are Sunday) or names (case-insensitive): SUN, MON, TUE, WED, THU, FRI, SAT

Examples

import { Cron } from "@jondotsoy/cron";

// Every minute
new Cron("* * * * *");

// At 22:00 on weekdays (Monday through Friday)
new Cron("0 22 * * 1-5");

// At minute 23 past every 2nd hour from 0 through 20
new Cron("23 0-20/2 * * *");

// At 04:05 on Sunday
new Cron("5 4 * * sun");

// At midnight on the 1st and 15th of each month
new Cron("0 0 1,15 * *");

// Every 2 minutes
new Cron("*/2 * * * *");

// At 04:00 on every day from 8th through 14th
new Cron("0 4 8-14 * *");

// In June, July, and August
new Cron("* * * jun-aug *");

// With specific year
new Cron("0 0 1 1 * 2025");

Testing

Run the test suite:

bun test

API

Cron Class

new Cron(rule: string, now?: Temporal.PlainDateTime)

Creates a new Cron instance.

  • rule: Cron expression string (5 or 6 fields, or special expression)
  • now: Optional starting date/time (defaults to current time using Temporal.Now.plainDateTimeISO())

Properties:

  • expression: The original cron expression string
  • now: The starting date/time
  • spec: The parsed cron specification (read-only)

Cron.next(cron: Cron): Temporal.PlainDateTime

Returns the next execution time for the given cron instance.

Parameters:

  • cron: The Cron instance to get the next execution time from

Returns: The next Temporal.PlainDateTime when the cron expression will match

Throws: Error if the cron expression is @reboot or no next datetime is found

Example:

const cron = new Cron("0 12 * * *"); // Daily at noon
const nextRun = Cron.next(cron);
console.log(nextRun.toString()); // Next occurrence at 12:00

Cron.take(cron: Cron, limit?: number): Temporal.PlainDateTime[]

Returns an array of the next N execution times for the given cron expression.

Parameters:

  • cron: The Cron instance to get execution times from
  • limit: The number of execution times to return (default: 1)

Returns: An array of Temporal.PlainDateTime objects when the cron expression will match

Throws: Error if the cron expression is @reboot

Example:

const cron = new Cron("0 */6 * * *"); // Every 6 hours
const next5Runs = Cron.take(cron, 5);
next5Runs.forEach((dt) => console.log(dt.toString()));

Cron.setInterval(callback: () => void, cron: Cron)

Schedules a callback to run at times matching the cron expression.

Special behavior for @reboot: Executes the callback immediately once and returns.

Returns an object with:

  • promise: Promise that resolves when the scheduler is aborted or completes
  • abort(): Function to stop the scheduler
  • [Symbol.dispose](): Function for automatic resource disposal (same as abort())
  • [Symbol.asyncDispose](): Async function that aborts and waits for the promise to complete

The returned object implements both the Disposable and AsyncDisposable protocols, allowing it to be used with the using and await using keywords in TypeScript 5.2+.

cron[Symbol.iterator]()

Makes the Cron instance iterable, yielding execution times indefinitely.

Note: Cannot iterate over @reboot expressions (throws an error).

CronFormat Class

new CronFormat(locale: string | Intl.Locale)

Creates a new CronFormat instance for formatting cron expressions into human-readable text.

  • locale: Locale string (e.g., "en", "es") or Intl.Locale object

Supported locales: en (English), es (Spanish)

format(cronExpression: Cron | string): string

Converts a cron expression into a human-readable description.

  • cronExpression: Cron instance or cron expression string
  • Returns: Human-readable string describing the cron schedule

Examples:

const formatter = new CronFormat("en");
formatter.format("0 22 * * 1-5"); // "At 22:00 on every day-of-week from Monday through Friday."
formatter.format("*/5 * * * *"); // "At every 5th minute."
formatter.format("@weekly"); // "At 00:00 on Sunday."

formatToParts(cronExpression: Cron | string): CronFormatPart[]

Converts a cron expression into an array of parts with type and value information. Useful for custom rendering or styling.

  • cronExpression: Cron instance or cron expression string
  • Returns: Array of CronFormatPart objects

Part types:

  • literal - Static text (e.g., "At ", " on ")
  • time - General time description
  • minute - Minute component
  • hour - Hour component
  • day - Day of month component
  • weekday - Day of week component
  • month - Month component

Example:

const formatter = new CronFormat("en");
const parts = formatter.formatToParts("5 4 * * *");
// [
//   { type: "literal", value: "At " },
//   { type: "hour", value: "04" },
//   { type: "literal", value: ":" },
//   { type: "minute", value: "05" },
//   { type: "literal", value: "." }
// ]

Dependencies

The Temporal object is also exported from this package for convenience:

import { Cron, Temporal } from "@jondotsoy/cron";

Internationalization (i18n)

The CronFormat class provides optional internationalization support for formatting cron expressions into human-readable text in different languages.

Supported Languages

Currently, the following locales are supported:

| Locale Code | Language | Example Output | | ----------- | -------- | ----------------------------------------------------------- | | en | English | "At 22:00 on every day-of-week from Monday through Friday." | | es | Spanish | "A las 22:00 cada día de la semana del lunes al viernes." |

Usage

import { CronFormat } from "@jondotsoy/cron";

// Using locale string
const formatterEn = new CronFormat("en");
const formatterEs = new CronFormat("es");

// Using Intl.Locale object
const formatter = new CronFormat(new Intl.Locale("es"));

// Format the same expression in different languages
const expression = "0 9 * * MON-FRI";

console.log(formatterEn.format(expression));
// Output: "At 09:00 on every day-of-week from Monday through Friday."

console.log(formatterEs.format(expression));
// Output: "A las 09:00 cada día de la semana del lunes al viernes."

Contributing New Languages

To add support for a new language, you can contribute by creating a new locale file following the existing pattern. Check the project repository for contribution guidelines.

Colloquial Language Support

For colloquial or regional language variants, you can use the @jondotsoy/cron/colloquial-cron-format export:

import { ColloquialCronFormat } from "@jondotsoy/cron/colloquial-cron-format";

// Chilean slang variant
const formatter = new ColloquialCronFormat("es-CL-Flaite");

console.log(formatter.format("0 9 * * MON-FRI"));
// Output: "La weá corre a las 09:00 del lunes al viernes."

console.log(formatter.format("*/15 * * * *"));
// Output: "La weá corre cada 15 minutos."

The ColloquialCronFormat class extends the standard CronFormat functionality to support regional and colloquial language variants. It implements the same interface, so you can use it as a drop-in replacement:

import { ColloquialCronFormat } from "@jondotsoy/cron/colloquial-cron-format";

const formatter = new ColloquialCronFormat("es-CL-Flaite");

// Same methods as CronFormat
const text = formatter.format("0 22 * * 1-5");
const parts = formatter.formatToParts("0 22 * * 1-5");

Utilities

@jondotsoy/cron/utils

The utils module provides helper functions for testing and generating random cron specifications.

randomSpec(): Spec

Generates a random cron specification for testing purposes. This is useful for fuzzing tests, generating test cases, or creating random schedules.

Returns: A randomly generated Spec object that can be used with Cron.fromSpec()

Behavior:

  • 10% chance of generating a @reboot special expression
  • 90% chance of generating a standard cron specification with random rules
  • Year field has 80% chance of being * (any), 20% chance of a specific range (2024-2030)
  • Each field can be:
    • Any value (*)
    • Specific value (e.g., 5)
    • Range (e.g., 1-5)
    • Step values (e.g., */2)
    • List of values (e.g., 1,3,5)

Example:

import { randomSpec } from "@jondotsoy/cron/utils";
import { Cron } from "@jondotsoy/cron";

// Generate a random cron specification
const spec = randomSpec();

// Create a Cron instance from the spec
const cron = Cron.fromSpec(spec);

console.log(cron.expression); // e.g., "*/5 0-20/2 1,15 * MON-FRI"

// Use it like any other cron expression
const nextRun = Cron.next(cron);
console.log(nextRun.toString());

Use Cases:

  • Fuzzing tests: Generate random cron expressions to test parser robustness
  • Property-based testing: Create diverse test cases automatically
  • Load testing: Generate random schedules for stress testing schedulers
  • Example generation: Create varied examples for documentation

Example with multiple random specs:

import { randomSpec } from "@jondotsoy/cron/utils";
import { Cron } from "@jondotsoy/cron";

// Generate 10 random cron expressions
for (let i = 0; i < 10; i++) {
  const spec = randomSpec();
  const cron = Cron.fromSpec(spec);
  console.log(`Random cron ${i + 1}: ${cron.expression}`);
}

License

MIT © 2025 Jonathan Delgado