├── .gitignore ├── README.md ├── example.js ├── index.js ├── package-lock.json ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # friendly-cron 2 | 3 | ## Installation 4 | 5 | `npm install friendly-cron` 6 | 7 | ## Usage 8 | 9 | const friendlyCron = require('friendly-cron') 10 | 11 | const pattern = friendlyCron('every 15 minutes') 12 | // returns 0 */15 * * * * 13 | 14 | ## API 15 | 16 | `friendly-cron` exposes a single function that returns either a cron expression string or null if the input string isn't parseable. 17 | 18 | It's a very simple matching function that looks for "second", "minute", "hour", "day", "month", or "year", optionally proceeded by a number. 19 | 20 | Example valid strings: 21 | - "every hour" 22 | - "every 15 minutes" 23 | - "10 days" 24 | 25 | ### Random offsets 26 | 27 | It's often the case that you want jobs to run at some interval, but you don't want everything running in batches at, say, the top of the hour. 28 | 29 | To add a random offset to your cron pattern, you can add the `{ random: true }` option, like so: 30 | 31 | const pattern = friendlyCron('every 15 minutes', { random: true }) 32 | // returns something like 34 0-59/15 * * * * 33 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | const friendlyCron = require('./index') 2 | const parser = require('cron-parser') 3 | 4 | // generate random offsets so we don't have everything land on the hour 5 | const pattern = friendlyCron('every 15 minutes', { random: true }) 6 | console.log(pattern) 7 | const interval = parser.parseExpression(pattern) 8 | 9 | console.log(interval.next().toString()) 10 | console.log(interval.next().toString()) 11 | console.log(interval.next().toString()) 12 | console.log(interval.next().toString()) 13 | console.log(interval.next().toString()) -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const places = 'second minute hour day month year'.split(' ') 2 | const maxes = [59, 59, 23, 30] 3 | 4 | module.exports = function(string, opts) { 5 | const match = string.match(/(\d+)? (second|minute|hour|day|month|year)/) 6 | const rand = opts && opts.random 7 | if (match) { 8 | let pattern = Array(6).fill('*') 9 | const count = match[1] || 1 10 | const interval = match[2] 11 | const intervalPlace = places.indexOf(interval) 12 | if (count !== 1) { 13 | pattern[intervalPlace] = `${rand ? Math.round(Math.random() * (maxes[intervalPlace]/count))+`-${maxes[intervalPlace]}` : '*'}/${count}` 14 | // pattern[intervalPlace] = `*/${count}` 15 | } 16 | for (let i=intervalPlace-1; i>=0; i--) { 17 | const fillVal = rand ? Math.round(Math.random() * maxes[i]) : 0 18 | pattern[i] = fillVal 19 | } 20 | return pattern.join(' ') 21 | } else { 22 | return null 23 | } 24 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "friendly-cron", 3 | "version": "0.0.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "cron-parser": { 8 | "version": "2.7.3", 9 | "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.7.3.tgz", 10 | "integrity": "sha512-t9Kc7HWBWPndBzvbdQ1YG9rpPRB37Tb/tTviziUOh1qs3TARGh3b1p+tnkOHNe1K5iI3oheBPgLqwotMM7+lpg==", 11 | "dev": true, 12 | "requires": { 13 | "is-nan": "^1.2.1", 14 | "moment-timezone": "^0.5.23" 15 | } 16 | }, 17 | "define-properties": { 18 | "version": "1.1.3", 19 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 20 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 21 | "dev": true, 22 | "requires": { 23 | "object-keys": "^1.0.12" 24 | } 25 | }, 26 | "is-nan": { 27 | "version": "1.2.1", 28 | "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.2.1.tgz", 29 | "integrity": "sha1-n69ltvttskt/XAYoR16nH5iEAeI=", 30 | "dev": true, 31 | "requires": { 32 | "define-properties": "^1.1.1" 33 | } 34 | }, 35 | "moment": { 36 | "version": "2.23.0", 37 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz", 38 | "integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==", 39 | "dev": true 40 | }, 41 | "moment-timezone": { 42 | "version": "0.5.23", 43 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.23.tgz", 44 | "integrity": "sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w==", 45 | "dev": true, 46 | "requires": { 47 | "moment": ">= 2.9.0" 48 | } 49 | }, 50 | "object-keys": { 51 | "version": "1.0.12", 52 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", 53 | "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", 54 | "dev": true 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "friendly-cron", 3 | "version": "0.0.2", 4 | "description": "Convert friendly strings to cron patterns", 5 | "main": "index.js", 6 | "author": "Jesse Kriss ", 7 | "license": "ISC", 8 | "scripts": { 9 | "test": "node test.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/jkriss/friendly-cron.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/jkriss/friendly-cron/issues" 17 | }, 18 | "homepage": "https://github.com/jkriss/friendly-cron#readme", 19 | "keywords": [ 20 | "cron" 21 | ], 22 | "devDependencies": { 23 | "cron-parser": "^2.7.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | 3 | const friendlyCron = require('./index') 4 | 5 | let pattern = friendlyCron('every 15 minutes') 6 | assert.equal(pattern, '0 */15 * * * *') 7 | 8 | pattern = friendlyCron('every hour') 9 | assert.equal(pattern, '0 0 * * * *') 10 | 11 | pattern = friendlyCron('every damn day') 12 | assert.equal(pattern, '0 0 0 * * *') 13 | 14 | pattern = friendlyCron('7 seconds') 15 | assert.equal(pattern, '*/7 * * * * *') 16 | 17 | pattern = friendlyCron('flubber') 18 | assert.equal(pattern, null) --------------------------------------------------------------------------------