A cron-expression validator for TypeScript/JavaScript projects.
TypeScript
82
393 commits
updated Oct 8, 2026
Cron-validate is a cron-expression validator written in TypeScript. The validation options are customizable and cron fields like seconds and years are supported.
Package is available on npm:
npm install -S cron-validate
import cron from 'cron-validate'
const cronResult = cron('* * * * *')
if (cronResult.isValid()) {
// !cronResult.isError()
// valid code
} else {
// error code
}
The cron function returns a Result-type, which is either Valid<T, E> or Err<T, E>.
For checking the returned result, just use result.isValid() or result.isError()
Both result types contain values:
import cron from 'cron-validate'
const cronResult = cron('* * * * *')
if (cronResult.isValid()) {
const validValue = cronResult.getValue()
// The valid value is a object containing all cron fields
console.log(validValue)
// In this case, it would be:
// { seconds: undefined, minutes: '*', hours: '*', daysOfMonth: '*', months: '*', daysOfWeek: '*', years: undefiend }
} else {
const errorValue = cronResult.getError()
// The error value contains an array of strings, which represent the cron validation errors.
console.log(errorValue) // string[] of error messages
}
Make sure to test the result type beforehand, because getValue() only works on Valid and getError() only works on Err. If you don't check, it will throw an error.
For further information, you can check out https://github.com/gDelgado14/neverthrow, because I used and modified his code for this package. (Therefor not every documented function on his package is available on this package.)
To configure the validator, cron-validate uses a preset system. There are already defined presets (default, npm-node-cron or aws), but you can also define your own preset to use for your system. You can also use the override property to set certain option on single cron validates.
The following presets are already defined by cron-validate:
To select a preset for your validation, you can simply do this:
cron('* * * * *', {
preset: 'npm-cron-schedule',
})
To define your own preset, use this:
registerOptionPreset('YOUR-PRESET-ID', {
presetId: 'YOUR-PRESET-ID',
useSeconds: false,
useYears: false,
useAliases: false, // optional, default to false
useBlankDay: false,
allowOnlyOneBlankDayField: false,
allowStepping: true, // optional, defaults to true
mustHaveBlankDayField: false, // optional, default to false
useLastDayOfMonth: false, // optional, default to false
useLastDayOfWeek: false, // optional, default to false
useNearestWeekday: false, // optional, default to false
useNthWeekdayOfMonth: false, // optional, default to false
seconds: {
minValue: 0,
maxValue: 59,
lowerLimit: 0, // optional, default to minValue
upperLimit: 59, // optional, default to maxValue
},
minutes: {
minValue: 0,
maxValue: 59,
lowerLimit: 0, // optional, default to minValue
upperLimit: 59, // optional, default to maxValue
},
hours: {
minValue: 0,
maxValue: 23,
lowerLimit: 0, // optional, default to minValue
upperLimit: 23, // optional, default to maxValue
},
daysOfMonth: {
minValue: 1,
maxValue: 31,
lowerLimit: 1, // optional, default to minValue
upperLimit: 31, // optional, default to maxValue
},
months: {
minValue: 0,
maxValue: 12,
lowerLimit: 0, // optional, default to minValue
upperLimit: 12, // optional, default to maxValue
},
daysOfWeek: {
minValue: 1,
maxValue: 7,
lowerLimit: 1, // optional, default to minValue
upperLimit: 7, // optional, default to maxValue
},
years: {
minValue: 1970,
maxValue: 2099,
lowerLimit: 1970, // optional, default to minValue
upperLimit: 2099, // optional, default to maxValue
},
})
The preset properties explained:
presetId: string
useSeconds: boolean
useYears: boolean
useAliases: boolean
useBlankDay: boolean
allowOnlyOneBlankDayField: boolean
allowStepping: boolean
mustHaveBlankDayField: boolean
allowOnlyOneBlankDayField, it means that there will always be either day or day of week as ?useLastDayOfMonth: boolean
L-2 would me the 2nd to last day of the month.useLastDayOfWeek: boolean
5L would mean the last friday of the month.useNearestWeekday: boolean
15W would mean the weekday (mon-fri) closest to the 15th when the 15th is on sat-sun.useNthWeekdayOfMonth: boolean
6#3 would mean the 3rd friday of the month (assuming 6 = friday).minValue: number
maxValue: number
lowerLimit?: number
upperLimit?: number
If you want to override a option for single cron validations, you can use the override property:
console.log(cron('* * * * * *', {
preset: 'default', // second field not supported in default preset
override: {
useSeconds: true // override preset option
}
}))
console.log(cron('* 10-20 * * * *', {
preset: 'default',
override: {
minutes: {
lowerLimit: 10, // override preset option
upperLimit: 20 // override preset option
}
}
}))
import cron from 'cron-validate'
console.log(cron('* * * * *').isValid()) // true
console.log(cron('* * * * *').isError()) // false
console.log(cron('* 2,3,4 * * *').isValid()) // true
console.log(cron('0 */2 */5 * *').isValid()) // true
console.log(cron('* * * * * *', { override: { useSeconds: true } }).isValid()) // true
console.log(cron('* * * * * *', { override: { useYears: true } }).isValid()) // true
console.log(
cron('30 * * * * *', {
override: {
useSeconds: true,
seconds: {
lowerLimit: 20,
upperLimit: 40,
},
},
}).isValid()
) // true
console.log(
cron('* 3 * * *', {
override: {
hours: {
lowerLimit: 0,
upperLimit: 2,
},
},
}).isValid()
) // false
console.log(
cron('* * ? * *', {
override: {
useBlankDay: true,
},
}).isValid()
) // true
console.log(
cron('* * ? * ?', {
override: {
useBlankDay: true,
allowOnlyOneBlankDayField: true,
},
}).isValid()
) // false
Overall
Maintained
Code review
Latest release
Releases this year
19 followers · starred Apr 2023
A cron-expression validator for TypeScript/JavaScript projects.
TypeScript
82
393 commits
updated Oct 8, 2026
Cron-validate is a cron-expression validator written in TypeScript. The validation options are customizable and cron fields like seconds and years are supported.
Package is available on npm:
npm install -S cron-validate
import cron from 'cron-validate'
const cronResult = cron('* * * * *')
if (cronResult.isValid()) {
// !cronResult.isError()
// valid code
} else {
// error code
}
The cron function returns a Result-type, which is either Valid<T, E> or Err<T, E>.
For checking the returned result, just use result.isValid() or result.isError()
Both result types contain values:
import cron from 'cron-validate'
const cronResult = cron('* * * * *')
if (cronResult.isValid()) {
const validValue = cronResult.getValue()
// The valid value is a object containing all cron fields
console.log(validValue)
// In this case, it would be:
// { seconds: undefined, minutes: '*', hours: '*', daysOfMonth: '*', months: '*', daysOfWeek: '*', years: undefiend }
} else {
const errorValue = cronResult.getError()
// The error value contains an array of strings, which represent the cron validation errors.
console.log(errorValue) // string[] of error messages
}
Make sure to test the result type beforehand, because getValue() only works on Valid and getError() only works on Err. If you don't check, it will throw an error.
For further information, you can check out https://github.com/gDelgado14/neverthrow, because I used and modified his code for this package. (Therefor not every documented function on his package is available on this package.)
To configure the validator, cron-validate uses a preset system. There are already defined presets (default, npm-node-cron or aws), but you can also define your own preset to use for your system. You can also use the override property to set certain option on single cron validates.
The following presets are already defined by cron-validate:
To select a preset for your validation, you can simply do this:
cron('* * * * *', {
preset: 'npm-cron-schedule',
})
To define your own preset, use this:
registerOptionPreset('YOUR-PRESET-ID', {
presetId: 'YOUR-PRESET-ID',
useSeconds: false,
useYears: false,
useAliases: false, // optional, default to false
useBlankDay: false,
allowOnlyOneBlankDayField: false,
allowStepping: true, // optional, defaults to true
mustHaveBlankDayField: false, // optional, default to false
useLastDayOfMonth: false, // optional, default to false
useLastDayOfWeek: false, // optional, default to false
useNearestWeekday: false, // optional, default to false
useNthWeekdayOfMonth: false, // optional, default to false
seconds: {
minValue: 0,
maxValue: 59,
lowerLimit: 0, // optional, default to minValue
upperLimit: 59, // optional, default to maxValue
},
minutes: {
minValue: 0,
maxValue: 59,
lowerLimit: 0, // optional, default to minValue
upperLimit: 59, // optional, default to maxValue
},
hours: {
minValue: 0,
maxValue: 23,
lowerLimit: 0, // optional, default to minValue
upperLimit: 23, // optional, default to maxValue
},
daysOfMonth: {
minValue: 1,
maxValue: 31,
lowerLimit: 1, // optional, default to minValue
upperLimit: 31, // optional, default to maxValue
},
months: {
minValue: 0,
maxValue: 12,
lowerLimit: 0, // optional, default to minValue
upperLimit: 12, // optional, default to maxValue
},
daysOfWeek: {
minValue: 1,
maxValue: 7,
lowerLimit: 1, // optional, default to minValue
upperLimit: 7, // optional, default to maxValue
},
years: {
minValue: 1970,
maxValue: 2099,
lowerLimit: 1970, // optional, default to minValue
upperLimit: 2099, // optional, default to maxValue
},
})
The preset properties explained:
presetId: string
useSeconds: boolean
useYears: boolean
useAliases: boolean
useBlankDay: boolean
allowOnlyOneBlankDayField: boolean
allowStepping: boolean
mustHaveBlankDayField: boolean
allowOnlyOneBlankDayField, it means that there will always be either day or day of week as ?useLastDayOfMonth: boolean
L-2 would me the 2nd to last day of the month.useLastDayOfWeek: boolean
5L would mean the last friday of the month.useNearestWeekday: boolean
15W would mean the weekday (mon-fri) closest to the 15th when the 15th is on sat-sun.useNthWeekdayOfMonth: boolean
6#3 would mean the 3rd friday of the month (assuming 6 = friday).minValue: number
maxValue: number
lowerLimit?: number
upperLimit?: number
If you want to override a option for single cron validations, you can use the override property:
console.log(cron('* * * * * *', {
preset: 'default', // second field not supported in default preset
override: {
useSeconds: true // override preset option
}
}))
console.log(cron('* 10-20 * * * *', {
preset: 'default',
override: {
minutes: {
lowerLimit: 10, // override preset option
upperLimit: 20 // override preset option
}
}
}))
import cron from 'cron-validate'
console.log(cron('* * * * *').isValid()) // true
console.log(cron('* * * * *').isError()) // false
console.log(cron('* 2,3,4 * * *').isValid()) // true
console.log(cron('0 */2 */5 * *').isValid()) // true
console.log(cron('* * * * * *', { override: { useSeconds: true } }).isValid()) // true
console.log(cron('* * * * * *', { override: { useYears: true } }).isValid()) // true
console.log(
cron('30 * * * * *', {
override: {
useSeconds: true,
seconds: {
lowerLimit: 20,
upperLimit: 40,
},
},
}).isValid()
) // true
console.log(
cron('* 3 * * *', {
override: {
hours: {
lowerLimit: 0,
upperLimit: 2,
},
},
}).isValid()
) // false
console.log(
cron('* * ? * *', {
override: {
useBlankDay: true,
},
}).isValid()
) // true
console.log(
cron('* * ? * ?', {
override: {
useBlankDay: true,
allowOnlyOneBlankDayField: true,
},
}).isValid()
) // false
Overall
Maintained
Code review
Latest release
Releases this year
19 followers · starred Apr 2023