Iteration capabilities for finding next/previous execution times, checking date ranges, and iterating through scheduled times with comprehensive date matching and boundary checking.
Get the next scheduled execution time based on the cron expression.
/**
* Find the next scheduled date based on the cron expression
* @returns The next scheduled date
* @throws Error if no next date within constraints or loop limit exceeded
*/
next(): CronDate;Usage Examples:
import { CronExpressionParser } from "cron-parser";
const hourly = CronExpressionParser.parse('0 * * * *');
const nextExecution = hourly.next();
console.log('Next hourly run:', nextExecution.toString());
// With timezone
const londonTime = CronExpressionParser.parse('0 9 * * 1-5', {
tz: 'Europe/London'
});
console.log('Next London 9 AM weekday:', londonTime.next().toString());
// Multiple calls advance the iterator
const daily = CronExpressionParser.parse('@daily');
console.log('Tomorrow:', daily.next().toString());
console.log('Day after tomorrow:', daily.next().toString());Get the previous scheduled execution time based on the cron expression.
/**
* Find the previous scheduled date based on the cron expression
* @returns The previous scheduled date
* @throws Error if no previous date within constraints or loop limit exceeded
*/
prev(): CronDate;Usage Examples:
const weekly = CronExpressionParser.parse('@weekly');
const lastExecution = weekly.prev();
console.log('Last weekly run:', lastExecution.toString());
// Navigate backwards through time
const monthly = CronExpressionParser.parse('@monthly');
console.log('Last month:', monthly.prev().toString());
console.log('Month before that:', monthly.prev().toString());Check if next or previous scheduled times exist within constraints.
/**
* Check if there is a next scheduled date within constraints
* @returns True if next date exists, false otherwise
*/
hasNext(): boolean;
/**
* Check if there is a previous scheduled date within constraints
* @returns True if previous date exists, false otherwise
*/
hasPrev(): boolean;Usage Examples:
// Check availability before calling next/prev
const limited = CronExpressionParser.parse('0 0 * * *', {
currentDate: '2023-12-01',
endDate: '2023-12-31'
});
if (limited.hasNext()) {
console.log('Next execution:', limited.next().toString());
} else {
console.log('No more executions within date range');
}
// Safe iteration
while (limited.hasNext()) {
const nextDate = limited.next();
console.log('Scheduled:', nextDate.toString());
// Break after reasonable number to avoid infinite loops
if (someCondition) break;
}Get multiple next or previous dates in a single call.
/**
* Get multiple scheduled dates
* @param limit - Number of dates to retrieve (positive for next, negative for previous)
* @returns Array of scheduled dates
*/
take(limit: number): CronDate[];Usage Examples:
const every15min = CronExpressionParser.parse('*/15 * * * *');
// Get next 5 executions
const next5 = every15min.take(5);
console.log('Next 5 executions:');
next5.forEach((date, i) => {
console.log(`${i + 1}: ${date.toString()}`);
});
// Get previous 3 executions (negative limit)
const prev3 = every15min.take(-3);
console.log('Previous 3 executions:');
prev3.forEach((date, i) => {
console.log(`${i + 1}: ${date.toString()}`);
});
// Safe batch retrieval (stops if no more dates available)
const dailyLimited = CronExpressionParser.parse('@daily', {
currentDate: '2023-12-28',
endDate: '2023-12-31'
});
const remaining = dailyLimited.take(10); // Will only return available dates
console.log(`Got ${remaining.length} dates instead of requested 10`);Reset the iterator position to a new date or the original starting date.
/**
* Reset the iterator's current date to a new date or the initial date
* @param newDate - Optional new date to reset to. If not provided, resets to initial date
*/
reset(newDate?: Date | CronDate): void;Usage Examples:
const hourly = CronExpressionParser.parse('0 * * * *', {
currentDate: '2023-01-01T00:00:00Z'
});
// Advance the iterator
console.log('First next:', hourly.next().toString());
console.log('Second next:', hourly.next().toString());
// Reset to initial date
hourly.reset();
console.log('After reset:', hourly.next().toString()); // Same as first next
// Reset to specific date
hourly.reset(new Date('2023-06-01T12:00:00Z'));
console.log('From June 1st:', hourly.next().toString());
// Reset with CronDate (preserving timezone)
const londonDate = new CronDate('2023-01-01T00:00:00Z', 'Europe/London');
hourly.reset(londonDate);
console.log('From London time:', hourly.next().toString());Check if a specific date matches the cron expression.
/**
* Check if the cron expression includes the given date
* @param date - Date to check against the expression
* @returns True if date matches the cron expression, false otherwise
*/
includesDate(date: Date | CronDate): boolean;Usage Examples:
const workdayMorning = CronExpressionParser.parse('0 9 * * 1-5'); // 9 AM weekdays
// Check specific dates
const monday9am = new Date('2023-01-02T09:00:00Z'); // Monday
const saturday9am = new Date('2023-01-07T09:00:00Z'); // Saturday
const monday10am = new Date('2023-01-02T10:00:00Z'); // Monday but 10 AM
console.log('Monday 9 AM matches:', workdayMorning.includesDate(monday9am)); // true
console.log('Saturday 9 AM matches:', workdayMorning.includesDate(saturday9am)); // false
console.log('Monday 10 AM matches:', workdayMorning.includesDate(monday10am)); // false
// Use with CronDate for timezone awareness
const nycTime = new CronDate('2023-01-02T14:00:00Z', 'America/New_York'); // 9 AM in NYC
console.log('NYC time matches:', workdayMorning.includesDate(nycTime));
// Practical usage: filtering dates
const dates = [
new Date('2023-01-02T09:00:00Z'), // Monday 9 AM
new Date('2023-01-03T09:00:00Z'), // Tuesday 9 AM
new Date('2023-01-07T09:00:00Z'), // Saturday 9 AM
];
const workdayDates = dates.filter(date => workdayMorning.includesDate(date));
console.log(`${workdayDates.length} dates match workday pattern`);Use ES6 iterator protocol for modern iteration patterns.
/**
* Returns an ES6 iterator for iterating through future CronDate instances
* @returns Iterator object for CronExpression that yields CronDate values
*/
[Symbol.iterator](): Iterator<CronDate>;Usage Examples:
const every30min = CronExpressionParser.parse('*/30 * * * *');
// Use with for...of (be careful with infinite sequences!)
let count = 0;
for (const date of every30min) {
console.log(`Execution ${count + 1}:`, date.toString());
// Always include a break condition to avoid infinite loops
if (++count >= 5) break;
}
// Use with iterator methods
const iterator = every30min[Symbol.iterator]();
console.log('First:', iterator.next().value.toString());
console.log('Second:', iterator.next().value.toString());
// Use with modern JavaScript features
const next10 = Array.from(
{ length: 10 },
() => every30min[Symbol.iterator]().next().value
);
console.log('Next 10 executions:', next10.map(d => d.toString()));
// Practical example: collect until end date
const limitedIterator = CronExpressionParser.parse('0 */6 * * *', {
currentDate: '2023-01-01',
endDate: '2023-01-02'
});
const allDates = [];
for (const date of limitedIterator) {
allDates.push(date);
// Iterator will naturally stop when hasNext() returns false
}
console.log(`Collected ${allDates.length} dates within range`);Convert expression back to cron string format.
/**
* Generate a string representation of the cron expression
* @param includeSeconds - Whether to include the seconds field in output
* @returns String representation of the cron expression
*/
stringify(includeSeconds?: boolean): string;
/**
* Returns the string representation of the cron expression
* Uses original expression if available, otherwise generates from fields
* @returns The cron expression string
*/
toString(): string;Usage Examples:
const expr = CronExpressionParser.parse('*/15 30 9-17 * * 1-5');
// Generate cron string without seconds (5-field format)
console.log('5-field format:', expr.stringify()); // "30 9-17 * * 1-5"
// Generate cron string with seconds (6-field format)
console.log('6-field format:', expr.stringify(true)); // "*/15 30 9-17 * * 1-5"
// toString() method (uses original or generates)
console.log('toString():', expr.toString()); // Original expression or generated
// Roundtrip test
const original = '0 */10 8-18 * * MON-FRI';
const parsed = CronExpressionParser.parse(original);
const regenerated = parsed.stringify(true);
console.log('Original:', original);
console.log('Regenerated:', regenerated);
// Note: Regenerated may differ (e.g., MON-FRI becomes 1-5) but is functionally equivalentWorking with expressions that have start/end date constraints.
// Time range constraints are set via CronExpressionOptions
interface TimeRangeOptions {
startDate?: Date | string | number | CronDate;
endDate?: Date | string | number | CronDate;
currentDate?: Date | string | number | CronDate;
}
// Error thrown when iteration goes outside time span
const TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE = 'Out of the time span range';
// Error thrown when iteration loop limit is exceeded (safety mechanism)
const LOOPS_LIMIT_EXCEEDED_ERROR_MESSAGE = 'Invalid expression, loop limit exceeded';Usage Examples:
// Create expression with time constraints
const constrained = CronExpressionParser.parse('0 0 * * *', {
startDate: '2023-01-01',
endDate: '2023-01-31',
currentDate: '2023-01-15'
});
try {
// This will work - within range
console.log('Next in range:', constrained.next().toString());
// Keep getting next dates until we hit the boundary
const allDates = constrained.take(50); // May return fewer than 50
console.log(`Got ${allDates.length} dates within range`);
} catch (error) {
if (error.message === TIME_SPAN_OUT_OF_BOUNDS_ERROR_MESSAGE) {
console.log('Reached end of allowed time span');
} else if (error.message === LOOPS_LIMIT_EXCEEDED_ERROR_MESSAGE) {
console.log('Invalid expression: iteration loop limit exceeded (safety mechanism)');
}
}
// Check boundaries
console.log('Has next:', constrained.hasNext());
console.log('Has prev:', constrained.hasPrev());
// Reset to test boundaries
constrained.reset(new Date('2023-01-31T23:59:59'));
console.log('At end, has next:', constrained.hasNext()); // false
constrained.reset(new Date('2023-01-01T00:00:01'));
console.log('At start, has prev:', constrained.hasPrev()); // false