or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdjob-management.mdrecurrence-rules.md

recurrence-rules.mddocs/

0

# Recurrence Rules

1

2

Flexible recurrence rule system for defining complex scheduling patterns with precise control over timing components in Node Schedule.

3

4

## Capabilities

5

6

### RecurrenceRule Class

7

8

Create complex recurring schedules using rule-based specifications with fine-grained control over timing.

9

10

```javascript { .api }

11

/**

12

* Create a recurrence rule for complex scheduling patterns

13

* @param {number|number[]|Range} [year] - Year specification

14

* @param {number|number[]|Range} [month] - Month specification (0-11, where 0=January)

15

* @param {number|number[]|Range} [date] - Day of month specification (1-31)

16

* @param {number|number[]|Range} [dayOfWeek] - Day of week specification (0-6, where 0=Sunday)

17

* @param {number|number[]|Range} [hour] - Hour specification (0-23)

18

* @param {number|number[]|Range} [minute] - Minute specification (0-59)

19

* @param {number|number[]|Range} [second] - Second specification (0-59, defaults to 0)

20

*/

21

function RecurrenceRule(year?, month?, date?, dayOfWeek?, hour?, minute?, second?);

22

23

class RecurrenceRule {

24

/** Year specification (4-digit year, null for any) */

25

year: number | number[] | Range | null;

26

/** Month specification (0-11, null for any) */

27

month: number | number[] | Range | null;

28

/** Day of month specification (1-31, null for any) */

29

date: number | number[] | Range | null;

30

/** Day of week specification (0-6, Sunday=0, null for any) */

31

dayOfWeek: number | number[] | Range | null;

32

/** Hour specification (0-23, null for any) */

33

hour: number | number[] | Range | null;

34

/** Minute specification (0-59, null for any) */

35

minute: number | number[] | Range | null;

36

/** Second specification (0-59, null for any) */

37

second: number | number[] | Range | null;

38

/** Whether this rule allows recurrence */

39

recurs: boolean;

40

/** Timezone identifier */

41

tz: string;

42

}

43

```

44

45

**Usage Examples:**

46

47

```javascript

48

const { RecurrenceRule, scheduleJob } = require('node-schedule');

49

50

// Every weekday at 9:30 AM

51

const rule1 = new RecurrenceRule();

52

rule1.dayOfWeek = [new Range(1, 5)]; // Monday to Friday

53

rule1.hour = 9;

54

rule1.minute = 30;

55

56

const job1 = scheduleJob(rule1, function() {

57

console.log('Weekday morning job');

58

});

59

60

// Every 15 minutes during business hours

61

const rule2 = new RecurrenceRule();

62

rule2.hour = [new Range(9, 17)]; // 9 AM to 5 PM

63

rule2.minute = [0, 15, 30, 45];

64

65

const job2 = scheduleJob(rule2, function() {

66

console.log('Business hours job');

67

});

68

69

// Last day of every month at midnight

70

const rule3 = new RecurrenceRule();

71

rule3.date = [28, 29, 30, 31]; // Will only fire on valid dates

72

rule3.hour = 0;

73

rule3.minute = 0;

74

75

const job3 = scheduleJob(rule3, function() {

76

console.log('Month-end job');

77

});

78

```

79

80

### RecurrenceRule Methods

81

82

Methods for validating and calculating recurrence rule behavior.

83

84

```javascript { .api }

85

/**

86

* Check if the recurrence rule configuration is valid

87

* @returns {boolean} True if rule is valid

88

*/

89

RecurrenceRule.prototype.isValid = function();

90

91

/**

92

* Calculate the next date that matches this recurrence rule

93

* @param {Date} [base] - Base date to calculate from (defaults to current time)

94

* @returns {Date|null} Next matching date or null if no future dates match

95

*/

96

RecurrenceRule.prototype.nextInvocationDate = function(base);

97

98

/**

99

* Internal method for calculating next invocation date (internal use)

100

* @param {Date} base - Base date to calculate from

101

* @returns {Date|null} Next matching date or null

102

*/

103

RecurrenceRule.prototype._nextInvocationDate = function(base);

104

```

105

106

### Range Class

107

108

Define ranges of values for use in recurrence rule specifications.

109

110

```javascript { .api }

111

/**

112

* Create a range for use in recurrence rules

113

* @param {number} [start=0] - Range start value (inclusive)

114

* @param {number} [end=60] - Range end value (inclusive)

115

* @param {number} [step=1] - Step between values in range

116

*/

117

function Range(start?, end?, step?);

118

119

class Range {

120

/** Range start value */

121

start: number;

122

/** Range end value */

123

end: number;

124

/** Step between values */

125

step: number;

126

}

127

```

128

129

**Usage Examples:**

130

131

```javascript

132

const { Range, RecurrenceRule, scheduleJob } = require('node-schedule');

133

134

// Every 5 minutes from 0 to 55

135

const every5Minutes = new Range(0, 55, 5); // 0, 5, 10, 15, ..., 55

136

137

const rule = new RecurrenceRule();

138

rule.minute = every5Minutes;

139

140

const job = scheduleJob(rule, function() {

141

console.log('Runs every 5 minutes');

142

});

143

144

// Business hours: 9 AM to 5 PM

145

const businessHours = new Range(9, 17);

146

rule.hour = businessHours;

147

148

// Weekdays only

149

const weekdays = new Range(1, 5); // Monday=1 to Friday=5

150

rule.dayOfWeek = weekdays;

151

```

152

153

### Range Methods

154

155

Methods for working with range objects.

156

157

```javascript { .api }

158

/**

159

* Check if a value falls within this range

160

* @param {number} val - Value to check

161

* @returns {boolean} True if the value is in the range

162

*/

163

Range.prototype.contains = function(val);

164

```

165

166

### Object Literal Recurrence

167

168

Alternative syntax using object literals instead of RecurrenceRule instances.

169

170

```javascript { .api }

171

/**

172

* Object-literal recurrence specification

173

* Each property can be a single value, array of values, or Range

174

*/

175

interface RecurrenceSpec {

176

/** Year specification */

177

year?: number | number[] | Range;

178

/** Month specification (0-11) */

179

month?: number | number[] | Range;

180

/** Day of month specification (1-31) */

181

date?: number | number[] | Range;

182

/** Day of week specification (0-6, Sunday=0) */

183

dayOfWeek?: number | number[] | Range;

184

/** Hour specification (0-23) */

185

hour?: number | number[] | Range;

186

/** Minute specification (0-59) */

187

minute?: number | number[] | Range;

188

/** Second specification (0-59) */

189

second?: number | number[] | Range;

190

}

191

```

192

193

**Usage Examples:**

194

195

```javascript

196

const schedule = require('node-schedule');

197

198

// Object literal syntax - every Tuesday and Thursday at 2:30 PM

199

const job1 = schedule.scheduleJob({

200

dayOfWeek: [2, 4], // Tuesday and Thursday

201

hour: 14,

202

minute: 30

203

}, function() {

204

console.log('Bi-weekly meeting reminder');

205

});

206

207

// Multiple values and ranges

208

const job2 = schedule.scheduleJob({

209

month: [0, 3, 6, 9], // Quarterly: Jan, Apr, Jul, Oct

210

date: 1, // First day of month

211

hour: 8,

212

minute: 0

213

}, function() {

214

console.log('Quarterly report');

215

});

216

217

// Complex scheduling with ranges

218

const { Range } = require('node-schedule');

219

220

const job3 = schedule.scheduleJob({

221

dayOfWeek: new Range(1, 5), // Weekdays

222

hour: [9, 12, 15], // 9 AM, noon, 3 PM

223

minute: [0, 30] // On the hour and half-hour

224

}, function() {

225

console.log('Regular check-in');

226

});

227

```

228

229

### Advanced Scheduling with Start/End Dates

230

231

Schedule jobs with recurrence rules and temporal boundaries.

232

233

```javascript { .api }

234

/**

235

* Schedule specification with temporal boundaries

236

*/

237

interface ScheduleSpec {

238

/** Recurrence rule or cron string */

239

rule: RecurrenceRule | string;

240

/** Start date for scheduling (job won't run before this) */

241

start?: Date;

242

/** End date for scheduling (job won't run after this) */

243

end?: Date;

244

/** Timezone for date calculations */

245

tz?: string;

246

}

247

```

248

249

**Usage Examples:**

250

251

```javascript

252

const schedule = require('node-schedule');

253

254

// Campaign that runs for a specific period

255

const campaignRule = new schedule.RecurrenceRule();

256

campaignRule.hour = [9, 12, 15, 18]; // 4 times daily

257

campaignRule.minute = 0;

258

259

const campaignJob = schedule.scheduleJob({

260

rule: campaignRule,

261

start: new Date('2024-01-01'),

262

end: new Date('2024-01-31'),

263

tz: 'America/New_York'

264

}, function() {

265

console.log('Campaign reminder');

266

});

267

268

// Event reminders leading up to a deadline

269

const reminderRule = new schedule.RecurrenceRule();

270

reminderRule.hour = 9;

271

reminderRule.minute = 0;

272

273

const reminderJob = schedule.scheduleJob({

274

rule: reminderRule,

275

start: new Date('2024-02-01'),

276

end: new Date('2024-02-14') // Valentine's Day

277

}, function() {

278

console.log('Valentine\'s Day reminder');

279

});

280

```

281

282

### Internal Functions

283

284

Low-level functions exposed primarily for testing and advanced use cases. These functions are part of the internal scheduling mechanism.

285

286

```javascript { .api }

287

/**

288

* Schedule an invocation for execution (internal use)

289

* @param {Invocation} invocation - Invocation to schedule

290

*/

291

function scheduleInvocation(invocation);

292

293

/**

294

* Cancel a pending invocation (internal use)

295

* @param {Invocation} invocation - Invocation to cancel

296

*/

297

function cancelInvocation(invocation);

298

299

/**

300

* Schedule the next recurrence of a recurring job (internal use)

301

* @param {RecurrenceRule} rule - Recurrence rule

302

* @param {Job} job - Job instance

303

* @param {Date} [prevDate] - Previous execution date

304

* @param {Date} [endDate] - Optional end date

305

* @returns {Invocation|null} Next invocation or null

306

*/

307

function scheduleNextRecurrence(rule, job, prevDate?, endDate?);

308

309

/**

310

* Comparator function for sorting invocations by fire date (internal use)

311

* @param {Invocation} a - First invocation

312

* @param {Invocation} b - Second invocation

313

* @returns {number} Comparison result for sorting

314

*/

315

function sorter(a, b);

316

317

/**

318

* Internal array of all scheduled invocations

319

* Used for internal scheduling management and testing

320

*/

321

const _invocations: Invocation[];

322

```

323

324

### Cron String Support

325

326

Node Schedule supports standard cron expressions with an optional seconds field.

327

328

**Cron Format:**

329

```

330

* * * * * *

331

┬ ┬ ┬ ┬ ┬ ┬

332

│ │ │ │ │ │

333

│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)

334

│ │ │ │ └───── month (1 - 12)

335

│ │ │ └────────── day of month (1 - 31)

336

│ │ └─────────────── hour (0 - 23)

337

│ └──────────────────── minute (0 - 59)

338

└───────────────────────── second (0 - 59, OPTIONAL)

339

```

340

341

**Usage Examples:**

342

343

```javascript

344

const schedule = require('node-schedule');

345

346

// Every 30 seconds

347

const job1 = schedule.scheduleJob('*/30 * * * * *', function() {

348

console.log('Every 30 seconds');

349

});

350

351

// At 2:30 PM every day

352

const job2 = schedule.scheduleJob('0 30 14 * * *', function() {

353

console.log('Daily at 2:30 PM');

354

});

355

356

// Every 5 minutes during business hours (9 AM - 5 PM) on weekdays

357

const job3 = schedule.scheduleJob('0 */5 9-17 * * 1-5', function() {

358

console.log('Business hours reminder');

359

});

360

361

// First day of every month at midnight

362

const job4 = schedule.scheduleJob('0 0 0 1 * *', function() {

363

console.log('Monthly job');

364

});

365

```

366

367

### Timezone Support

368

369

Handle scheduling across different timezones using timezone identifiers.

370

371

**Usage Examples:**

372

373

```javascript

374

const schedule = require('node-schedule');

375

376

// Schedule in specific timezone

377

const rule = new schedule.RecurrenceRule();

378

rule.hour = 9;

379

rule.minute = 0;

380

rule.tz = 'America/New_York';

381

382

const easternJob = schedule.scheduleJob(rule, function() {

383

console.log('9 AM Eastern Time job');

384

});

385

386

// Multiple timezone jobs

387

const timezones = ['America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles'];

388

389

timezones.forEach(tz => {

390

const tzRule = new schedule.RecurrenceRule();

391

tzRule.hour = 8;

392

tzRule.minute = 0;

393

tzRule.tz = tz;

394

395

schedule.scheduleJob(`morning-${tz.split('/')[1]}`, tzRule, function() {

396

console.log(`Good morning from ${tz}!`);

397

});

398

});

399

```

400

401

### Rule Validation

402

403

Examples of valid and invalid rule configurations.

404

405

**Usage Examples:**

406

407

```javascript

408

const { RecurrenceRule, Range } = require('node-schedule');

409

410

// Valid rules

411

const validRule1 = new RecurrenceRule();

412

validRule1.month = new Range(0, 11); // All months

413

validRule1.hour = 12;

414

console.log('Valid:', validRule1.isValid()); // true

415

416

const validRule2 = new RecurrenceRule();

417

validRule2.dayOfWeek = [0, 6]; // Weekends

418

validRule2.hour = [10, 14, 18];

419

console.log('Valid:', validRule2.isValid()); // true

420

421

// Invalid rules (will return false for isValid())

422

const invalidRule1 = new RecurrenceRule();

423

invalidRule1.hour = 25; // Hours only go 0-23

424

console.log('Invalid hour:', invalidRule1.isValid()); // false

425

426

const invalidRule2 = new RecurrenceRule();

427

invalidRule2.minute = -5; // Minutes must be 0-59

428

console.log('Invalid minute:', invalidRule2.isValid()); // false

429

430

const invalidRule3 = new RecurrenceRule();

431

invalidRule3.month = 1; // February

432

invalidRule3.date = 30; // February never has 30 days

433

console.log('Invalid date:', invalidRule3.isValid()); // false

434

435

// Testing next invocation calculation

436

const testRule = new RecurrenceRule();

437

testRule.hour = 9;

438

testRule.minute = 0;

439

440

const nextRun = testRule.nextInvocationDate();

441

console.log('Next 9 AM:', nextRun);

442

443

// Rule that will never match (returns null)

444

const neverRule = new RecurrenceRule();

445

neverRule.year = 2020; // Past year

446

neverRule.month = 1;

447

neverRule.date = 1;

448

449

const neverDate = neverRule.nextInvocationDate();

450

console.log('Never runs:', neverDate); // null

451

```

452

453

### Error Handling

454

455

Common error scenarios and their handling:

456

457

**Usage Examples:**

458

459

```javascript

460

const schedule = require('node-schedule');

461

462

try {

463

// This will throw RangeError: Invalid number of arguments

464

const invalidJob = schedule.scheduleJob(function() {

465

console.log('Missing schedule spec');

466

});

467

} catch (error) {

468

console.error('Scheduling error:', error.message);

469

}

470

471

try {

472

// This will throw RangeError: The job method must be a function

473

const invalidJob = schedule.scheduleJob('0 * * * *', 'not a function');

474

} catch (error) {

475

console.error('Job method error:', error.message);

476

}

477

478

// Invalid cron expression handling

479

const badCronJob = schedule.scheduleJob('invalid cron', function() {

480

console.log('This will not be scheduled');

481

});

482

console.log('Bad cron job:', badCronJob); // null

483

484

// Rescheduling one-off jobs by name throws Error

485

const oneOffJob = schedule.scheduleJob('oneOff', new Date(Date.now() + 5000), function() {

486

console.log('One-off job');

487

});

488

489

try {

490

schedule.rescheduleJob('oneOff', new Date(Date.now() + 10000));

491

} catch (error) {

492

console.error('Reschedule error:', error.message); // Cannot reschedule one-off job by name

493

}

494

```