Skip to content

Instantly share code, notes, and snippets.

@kjhangiani
Last active October 18, 2016 20:44
Show Gist options
  • Save kjhangiani/d019f2bb0ea826c7791d0c3e73d8df40 to your computer and use it in GitHub Desktop.
Save kjhangiani/d019f2bb0ea826c7791d0c3e73d8df40 to your computer and use it in GitHub Desktop.
CRON to Dates API Endpoint

Cron2Date Parser

Summary

Create a javascript/node.js API endpoint that accepts a json payload of cron strings, and returns a json payload of valid dates for these strings. Include any applicable tests for this endpoint using the testing platform of your choice.

Details

Assume in our client software that we have a model defined as a "Frequency"

Each frequency contains two attributes: <string> name and <Array> crons. The name is guaranteed to be unique and the cron is a javascript array of strings (with cron format of "* * * * * *" representing "[sec] [min] [hr] [date] [month] [day of week]"). These cron strings determine when models implementing this frequency are processed. In this example, all cron strings will have "0 0 0" as the first 3 values, as we are interested only in dates, not times.

Thus, for example, let's say we had the following periods in our client:

[{
  name: "Monthly",
  crons: ["0 0 0 25 * *"] //the 25th of every month
},
{
  name: "Weekly",
  crons: ["0 0 0 * * 5"] //every friday
},
{
  name: "BiWeekly",
  crons: ["0 0 0 20 * *", "0 0 0 10 * *"] //the 10th and 20th of every month
},
{
  name: "Quarterly",
  crons: ["0 0 0 25 3 *", "0 0 0 27 6 *", "0 0 0 30 9 *", "0 0 0 22 12 *", "0 0 0 25 3 *"] //Mar 25, Jun 27, Sep 30, and Dec 22 - note duplicated Mar 25 entry
}]

We want an API endpoint that accepts this array of frequencies, as well as a given start_date and end_date range (such as Jan 1, 2016 to Jan 31, 2016) and will return the valid date objects that fall within this range for each period. We want to accomplish this using a single API request. The returned dates for each period should be sorted in ascending order, and not contain any duplicates.

The response json should be keyed by the frequency name (assume its a unique alphanumeric string).

Thus, the API endpoint will receive json structured like the following:

{
  start_date: new Date('2016-02-01 00:00:00'),
  end_date: new Date('2016-02-28 00:00:00'),
  frequencies: [
    {
      name: "Monthly",
      crons: ["0 0 0 25 * *"] //the 25th of every month
    },
    {
      name: "BiWeekly",
      crons: ["0 0 0 20 * *", "0 0 0 10 * *"] //the 10th and 20th of every month
    },
    {
      name: "Weekly",
      crons: ["0 0 0 * * 5"] //every friday
    },
    {
      name: "Quarterly",
      crons: ["0 0 0 25 3 *", "0 0 0 27 6 *", "0 0 0 30 9 *", "0 0 0 22 12 *", "0 0 0 25 3 *"] //Mar 25, Jun 27, Sep 30, and Dec 22 - note duplicated Mar 25 entry
    }]
}

And the expected response would be the following:

{
  Monthly: [new Date('2016-02-25 00:00:00')],
  Weekly: [new Date('2016-02-05 00:00:00'), new Date('2016-02-12 00:00:00'), new Date('2016-02-19 00:00:00'), new Date('2016-02-26 00:00:00')],
  BiWeekly: [new Date('2016-02-10 00:00:00'), new Date('2016-02-20 00:00:00')], //note that these dates are sorted in ascending order
  Quarterly: null, [], or omit this key entirely as there are no valid dates
}

The following assumptions can be made:

  • All dates will be represented in UTC, don't worry about time zone conversions
  • All cron strings will use "0 0 0" for the seconds, minutes, and hour attributes, as we are interested only in dates, not times.
  • Cron strings will be valid
  • Frequency names will be unique
  • Each Frequency will contain at least one cron string.

You CANNOT assume:

  • That there will be any valid dates within the specified date range
  • That the cron strings will be in ascending order
  • That the resultant dates will not be duplicated (you need to de-duplicate dates before processing response)

You can use the following library to parse crons: https://www.npmjs.com/package/cron-parser

Note one gotcha is that this library throws an error if the cron string does not result in any valid dates for the specified period - you need to catch and handle this error, as it is NOT an error for the purposes of this exercise - if there are no valid dates, return an empty array or null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment