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 🙏

© 2024 – Pkg Stats / Ryan Hefner

cron-bomb

v0.1.0

Published

A simple and succinct JavaScript library for generating recurring events from a single object.

Downloads

11

Readme

Description

A simple and succinct JavaScript library for generating recurring events from a single object.

Often it is necessary to manage recurring events. Keeping track of public holidays, managing recurring bookings for your clients, or recording the opening hours of businesses all require a solution to this problem.

Current ways to manage recurring dates

Option 1:

The naive way to solve this problem is to explicitly generate an object for every occurrence and store all generated objects in a database. Of course, there are infinitely many events, so this process must be chunked into blocks of, let's say 6 months, and then 6 months later the process must be repeated. This is very manual, takes up a lot of space in your db, and is expensive to send over a network.

Option 2:

Another solution is to create a second database model that keeps track of how often the event should repeat. It generally has fields like second, minute, hour, day, month, year to represent how often to repeat. This object is then referenced by the event object with a foreign key or similar. This also has some drawbacks. For example, it becomes difficult to describe events that repeat the third Saturday of every month.

Enter cron-bomb

Cron-bomb is similar to option 2, in that it can describe an infinite series of repeating events. However, it offers a number of additional advantages:

  • It can simply describe a richer variety of recurring events, like every weekday, or every third Saturday of the month.
  • It doesn't need an extra database model, or foreign keys. It can be represented by a single field in your current model.
  • It's even less expensive to send over a network.
  • Provides inbuilt ways of tracking things like cancelled appointments, and booking clashes.

Installation

$ npm install cron-bomb --save

Usage

Parameters

explode()

| Parameter | Description | Default | |-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------| | data | An object (or array of objects) with a 'cron' key. Any other key:value pairs present in the data param will be persisted in the output. | {} | | options.start | A JS Date object representing the beginning of the date range to explode. | new Date() | | options.end, | A JS Date object representing the beginning of the date range to explode. | New Date() | | options.field | The field in 'data' to check for a crontab | 'cron' | | options.exclude | An array of JS Date objects. Objects matching these dates will not be present in the exploded array. | [] | | options.utc | Whether to explode the dates in UTC time or in the current timezone | false | | options.sorted | If an array of objects is passed into the data param, the output will be ordered by their place in the input array. If sorted is set to true, the output will be sorted by Date. | false |

intersection()

Basic Usage

  import { explode } from 'cron-bomb';

  const start = new Date(2020, 0, 1, 0, 0);
  const end = new Date(2020, 0, 8, 0, 0);
  const data = {
    title: 'Lord Of The Fries',
    cron: '10 0 * * 1-5', // Every weekday at 11am
  };

  const debris = explode(data, {start, end})
  console.log(JSON.stringify(debris, null, 2));

This will print the following:

[
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-01T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-02T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-03T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-06T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-07T00:10:00.000Z"
  }
]

So, what just happened? Basically, we just asked cron-bomb to give us a list of all dates between 2020-01-01 and 2020-01-07 that match 10 0 * * 1-5. Notice that the 4th and 5th of January, 2020 were skipped because these are not weekdays. An array was then returned where each element is an object that looks a lot like the original object that we passed in, except the cron value has been replaced with a Date.

Custom field name

By default, cron-bomb will look for a field called cron and use that. However, it's possible to specify any field name you want by adding it to the options:

  import { explode } from 'cron-bomb';

  const start = new Date(2020, 0, 1, 0, 0);
  const end = new Date(2020, 0, 8, 0, 0);
  const data = {
    title: 'Lord Of The Fries',
    foo: '10 0 * * 1-5', // Every weekday at 11am
  };

  const debris = explode(data, {start, end, field: 'foo'})

  console.log(JSON.stringify(debris, null, 2));

The field name will be reflected in the output array as well:

[
  {
    "title": "Lord Of The Fries",
    "foo": "2020-01-01T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "foo": "2020-01-02T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "foo": "2020-01-03T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "foo": "2020-01-06T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "foo": "2020-01-07T00:10:00.000Z"
  }
]

Passing multiple objects to explode

cron-bomb accepts either an Object, or an Array as input for the data option. This means you can easily explode multiple objects at once:

import { explode } from 'cron-bomb';

const start = new Date(Date.UTC(2020, 0, 1, 0, 0));
const end = new Date(Date.UTC(2020, 0, 3, 0, 0));
const data = [{
  title: 'Lord Of The Fries',
  cron: '10 0 * * 1-5', // Every weekday at 11am
},
{
  title: 'Lords Of The Fry',
  cron: '10 0 * * 1-5', // Every weekday at 11am
}];

const debris = explode(data, {start, end});
console.log(JSON.stringify(debris, null, 2));

This returns the following:

[
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-01T00:10:00.000Z"
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2020-01-02T00:10:00.000Z"
  },
  {
    "title": "Lords Of The Fry",
    "cron": "2020-01-01T00:10:00.000Z"
  },
  {
    "title": "Lords Of The Fry",
    "cron": "2020-01-02T00:10:00.000Z"
  }
]

Note that the returned array is ordered in regards to the elements in the array that was passed in, not by date. A sortable option which will use insertion sort to sort the array by date is in development and will be available in a future version. This will be more efficient than sorting the array after it is returned, but for now, it is relatively trivial to sort the returned array by date.

Excluding Particular dates

A common use case might be that an event is meant to repeat every week, but due to unforeseen circumstances, particular instances have been cancelled. For this, you can pass an array of excluded dates to cron-bomb and they will be skipped in the returned array:

import { explode } from 'cron-bomb';

const start = new Date('October 1, 2019');
const end = new Date('October 8, 2019');
const data = {
  title: 'Lord Of The Fries',
  cron: '10 0 * * 1-5', // Every weekday at 11am
  duration: 12, // Closes at 11pm
};

const cancelledEvents = [new Date('2019-10-07T13:10:00.000Z')];
const debris = explode(data, {start, end, exclude: cancelledEvents});
console.log(JSON.stringify(debris, null, 2));
[
  {
    "title": "Lord Of The Fries",
    "cron": "2019-10-01T14:10:00.000Z",
    "duration": 12
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2019-10-02T14:10:00.000Z",
    "duration": 12
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2019-10-03T14:10:00.000Z",
    "duration": 12
  },
  {
    "title": "Lord Of The Fries",
    "cron": "2019-10-06T13:10:00.000Z",
    "duration": 12
  }
]

Note that the last day is now being skipped.

Intersections

Another common use case is that you have two streams of recurring events and want see if they ever overlap. For example, this might be a booking that repeats weekly unless it's a public holiday. cron-bomb supplies functionality to help you do that:

Help with crontab syntax

https://crontab.guru/