or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access-control.mdattendees.mdcalendars.mdconferences.mdcore-operations.mdevents.mdfree-busy.mdindex.mdrecurrence.mdreminders.md

recurrence.mddocs/

0

# Recurrence and Scheduling

1

2

GCSA provides powerful recurrence capabilities through the Recurrence class and Duration utilities. These classes enable creation of recurring events with complex scheduling patterns using RRULE (RFC 5545) format, exception handling, and flexible timing options.

3

4

## Package Information

5

6

```python

7

from gcsa.recurrence import (

8

Recurrence, Duration,

9

SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY,

10

SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY,

11

SU, MO, TU, WE, TH, FR, SA,

12

DEFAULT_WEEK_START

13

)

14

```

15

16

## Recurrence Class

17

18

### Basic Recurrence Rules

19

20

```python { .api }

21

class Recurrence:

22

@staticmethod

23

def rule(

24

freq,

25

until = None,

26

count = None,

27

interval = None,

28

by_month = None,

29

by_month_day = None,

30

by_year_day = None,

31

by_week_no = None,

32

by_weekday = None,

33

by_hour = None,

34

by_minute = None,

35

by_second = None,

36

by_set_pos = None,

37

week_start = None

38

):

39

"""

40

Create a recurrence rule (RRULE) string.

41

42

:param freq: Frequency of recurrence (SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY)

43

:param until: End date/time for recurrence (datetime object)

44

:param count: Number of occurrences (int)

45

:param interval: Interval between occurrences (int, default=1)

46

:param by_month: Month(s) for recurrence (1-12, list or int)

47

:param by_month_day: Day(s) of month for recurrence (1-31, -31 to -1, list or int)

48

:param by_year_day: Day(s) of year for recurrence (1-366, -366 to -1, list or int)

49

:param by_week_no: Week number(s) for recurrence (1-53, -53 to -1, list or int)

50

:param by_weekday: Weekday(s) for recurrence (SU-SA, list or string)

51

:param by_hour: Hour(s) for recurrence (0-23, list or int)

52

:param by_minute: Minute(s) for recurrence (0-59, list or int)

53

:param by_second: Second(s) for recurrence (0-59, list or int)

54

:param by_set_pos: Position(s) in set (1-366, -366 to -1, list or int)

55

:param week_start: First day of week (SU-SA, default=SU)

56

:return: RRULE string

57

"""

58

```

59

60

### Exception Rules and Dates

61

62

```python { .api }

63

@staticmethod

64

def exclude_rule(

65

freq,

66

until = None,

67

count = None,

68

interval = None,

69

by_month = None,

70

by_month_day = None,

71

by_year_day = None,

72

by_week_no = None,

73

by_weekday = None,

74

by_hour = None,

75

by_minute = None,

76

by_second = None,

77

by_set_pos = None,

78

week_start = None

79

):

80

"""

81

Create an exception rule (EXRULE) string to exclude occurrences.

82

83

Parameters same as rule() method.

84

:return: EXRULE string

85

"""

86

87

@staticmethod

88

def dates(*dates):

89

"""

90

Convert dates to RDATE format for including specific dates.

91

92

:param dates: Date objects to include

93

:return: RDATE string

94

"""

95

96

@staticmethod

97

def times(*datetimes):

98

"""

99

Convert datetimes to RDATE format for including specific times.

100

101

:param datetimes: Datetime objects to include

102

:return: RDATE string

103

"""

104

105

@staticmethod

106

def periods(*periods):

107

"""

108

Convert periods to RDATE format for including specific periods.

109

110

:param periods: Period tuples (start, end) to include

111

:return: RDATE string

112

"""

113

114

@staticmethod

115

def exclude_dates(*dates):

116

"""

117

Convert dates to EXDATE format for excluding specific dates.

118

119

:param dates: Date objects to exclude

120

:return: EXDATE string

121

"""

122

123

@staticmethod

124

def exclude_times(*datetimes):

125

"""

126

Convert datetimes to EXDATE format for excluding specific times.

127

128

:param datetimes: Datetime objects to exclude

129

:return: EXDATE string

130

"""

131

132

@staticmethod

133

def exclude_periods(*periods):

134

"""

135

Convert periods to EXDATE format for excluding specific periods.

136

137

:param periods: Period tuples (start, end) to exclude

138

:return: EXDATE string

139

"""

140

```

141

142

## Duration Class

143

144

```python { .api }

145

class Duration:

146

def __init__(

147

self,

148

w = None, # weeks

149

d = None, # days

150

h = None, # hours

151

m = None, # minutes

152

s = None # seconds

153

):

154

"""

155

Create a duration for use in recurrence rules.

156

157

:param w: Number of weeks

158

:param d: Number of days

159

:param h: Number of hours

160

:param m: Number of minutes

161

:param s: Number of seconds

162

"""

163

```

164

165

## Frequency Constants

166

167

```python { .api }

168

# Recurrence frequency options

169

SECONDLY = "SECONDLY" # Every second

170

MINUTELY = "MINUTELY" # Every minute

171

HOURLY = "HOURLY" # Every hour

172

DAILY = "DAILY" # Every day

173

WEEKLY = "WEEKLY" # Every week

174

MONTHLY = "MONTHLY" # Every month

175

YEARLY = "YEARLY" # Every year

176

```

177

178

## Weekday Constants

179

180

```python { .api }

181

# Day constants for recurrence rules

182

SUNDAY = SU = "SU" # Sunday

183

MONDAY = MO = "MO" # Monday

184

TUESDAY = TU = "TU" # Tuesday

185

WEDNESDAY = WE = "WE" # Wednesday

186

THURSDAY = TH = "TH" # Thursday

187

FRIDAY = FR = "FR" # Friday

188

SATURDAY = SA = "SA" # Saturday

189

190

# Default week start

191

DEFAULT_WEEK_START = SUNDAY

192

```

193

194

## Basic Usage Examples

195

196

### Simple Recurring Events

197

198

```python

199

from gcsa.google_calendar import GoogleCalendar

200

from gcsa.event import Event

201

from gcsa.recurrence import Recurrence, DAILY, WEEKLY, MONTHLY

202

from datetime import datetime, date

203

204

gc = GoogleCalendar()

205

206

# Daily recurring event

207

daily_standup = Event(

208

summary="Daily Standup",

209

start=datetime(2024, 1, 15, 9, 0),

210

end=datetime(2024, 1, 15, 9, 15),

211

recurrence=[

212

Recurrence.rule(freq=DAILY, count=30) # 30 occurrences

213

]

214

)

215

gc.add_event(daily_standup)

216

217

# Weekly recurring event

218

weekly_meeting = Event(

219

summary="Team Meeting",

220

start=datetime(2024, 1, 15, 10, 0),

221

end=datetime(2024, 1, 15, 11, 0),

222

recurrence=[

223

Recurrence.rule(freq=WEEKLY, until=datetime(2024, 6, 15)) # Until June 15

224

]

225

)

226

gc.add_event(weekly_meeting)

227

228

# Monthly recurring event

229

monthly_review = Event(

230

summary="Monthly Review",

231

start=datetime(2024, 1, 1, 14, 0),

232

end=datetime(2024, 1, 1, 15, 0),

233

recurrence=[

234

Recurrence.rule(freq=MONTHLY, interval=1, count=12) # Monthly for 1 year

235

]

236

)

237

gc.add_event(monthly_review)

238

```

239

240

### Weekday-Specific Recurring Events

241

242

```python

243

from gcsa.recurrence import Recurrence, WEEKLY, MONDAY, WEDNESDAY, FRIDAY

244

from gcsa.event import Event

245

from datetime import datetime

246

247

# Every Monday, Wednesday, and Friday

248

mwf_workout = Event(

249

summary="Workout Session",

250

start=datetime(2024, 1, 15, 7, 0), # Start on a Monday

251

end=datetime(2024, 1, 15, 8, 0),

252

recurrence=[

253

Recurrence.rule(

254

freq=WEEKLY,

255

by_weekday=[MONDAY, WEDNESDAY, FRIDAY],

256

count=36 # 12 weeks × 3 days

257

)

258

]

259

)

260

gc.add_event(mwf_workout)

261

262

# Every Tuesday and Thursday

263

tt_meetings = Event(

264

summary="Client Check-in",

265

start=datetime(2024, 1, 16, 15, 0), # Start on a Tuesday

266

end=datetime(2024, 1, 16, 15, 30),

267

recurrence=[

268

Recurrence.rule(

269

freq=WEEKLY,

270

by_weekday=[TU, TH], # Can use short forms

271

until=datetime(2024, 12, 31)

272

)

273

]

274

)

275

gc.add_event(tt_meetings)

276

```

277

278

### Advanced Monthly Patterns

279

280

```python

281

from gcsa.recurrence import Recurrence, MONTHLY, FRIDAY

282

from gcsa.event import Event

283

from datetime import datetime

284

285

# First Friday of every month

286

first_friday = Event(

287

summary="First Friday Drinks",

288

start=datetime(2024, 2, 2, 17, 0), # First Friday in Feb

289

end=datetime(2024, 2, 2, 19, 0),

290

recurrence=[

291

Recurrence.rule(

292

freq=MONTHLY,

293

by_weekday=FRIDAY,

294

by_set_pos=1 # First occurrence

295

)

296

]

297

)

298

gc.add_event(first_friday)

299

300

# Last day of every month

301

month_end_report = Event(

302

summary="Month End Report Due",

303

start=datetime(2024, 1, 31, 17, 0),

304

end=datetime(2024, 1, 31, 17, 30),

305

recurrence=[

306

Recurrence.rule(

307

freq=MONTHLY,

308

by_month_day=-1 # Last day of month

309

)

310

]

311

)

312

gc.add_event(month_end_report)

313

314

# 15th of every month

315

mid_month_review = Event(

316

summary="Mid-Month Review",

317

start=datetime(2024, 1, 15, 10, 0),

318

end=datetime(2024, 1, 15, 11, 0),

319

recurrence=[

320

Recurrence.rule(

321

freq=MONTHLY,

322

by_month_day=15,

323

count=12

324

)

325

]

326

)

327

gc.add_event(mid_month_review)

328

```

329

330

### Yearly Recurring Events

331

332

```python

333

from gcsa.recurrence import Recurrence, YEARLY

334

from gcsa.event import Event

335

from datetime import datetime

336

337

# Annual company retreat

338

annual_retreat = Event(

339

summary="Annual Company Retreat",

340

start=datetime(2024, 6, 15, 9, 0),

341

end=datetime(2024, 6, 16, 17, 0), # 2-day event

342

recurrence=[

343

Recurrence.rule(

344

freq=YEARLY,

345

by_month=6, # June

346

by_month_day=15, # 15th

347

count=5 # Next 5 years

348

)

349

]

350

)

351

gc.add_event(annual_retreat)

352

353

# Birthday recurring event

354

birthday = Event(

355

summary="John's Birthday",

356

start=date(2024, 3, 10),

357

end=date(2024, 3, 11),

358

recurrence=[

359

Recurrence.rule(freq=YEARLY) # Every year forever

360

]

361

)

362

gc.add_event(birthday)

363

```

364

365

### Complex Intervals and Patterns

366

367

```python

368

from gcsa.recurrence import Recurrence, DAILY, WEEKLY, MONTHLY

369

from gcsa.event import Event

370

from datetime import datetime

371

372

# Every other day

373

every_other_day = Event(

374

summary="Alternate Day Workout",

375

start=datetime(2024, 1, 15, 6, 0),

376

end=datetime(2024, 1, 15, 7, 0),

377

recurrence=[

378

Recurrence.rule(

379

freq=DAILY,

380

interval=2, # Every 2 days

381

count=50

382

)

383

]

384

)

385

gc.add_event(every_other_day)

386

387

# Every 3 weeks

388

tri_weekly = Event(

389

summary="Tri-weekly Sprint Planning",

390

start=datetime(2024, 1, 15, 9, 0),

391

end=datetime(2024, 1, 15, 10, 30),

392

recurrence=[

393

Recurrence.rule(

394

freq=WEEKLY,

395

interval=3, # Every 3 weeks

396

by_weekday=MONDAY

397

)

398

]

399

)

400

gc.add_event(tri_weekly)

401

402

# Quarterly meetings (every 3 months)

403

quarterly = Event(

404

summary="Quarterly Business Review",

405

start=datetime(2024, 1, 31, 14, 0),

406

end=datetime(2024, 1, 31, 16, 0),

407

recurrence=[

408

Recurrence.rule(

409

freq=MONTHLY,

410

interval=3, # Every 3 months

411

by_month_day=-1 # Last day of quarter-ending month

412

)

413

]

414

)

415

gc.add_event(quarterly)

416

```

417

418

### Recurring Events with Exceptions

419

420

```python

421

from gcsa.recurrence import Recurrence, WEEKLY, MONDAY

422

from gcsa.event import Event

423

from datetime import datetime, date

424

425

# Weekly meeting with holiday exceptions

426

weekly_with_exceptions = Event(

427

summary="Weekly Staff Meeting",

428

start=datetime(2024, 1, 8, 10, 0),

429

end=datetime(2024, 1, 8, 11, 0),

430

recurrence=[

431

# Main rule: every Monday

432

Recurrence.rule(freq=WEEKLY, by_weekday=MONDAY, count=52),

433

434

# Exclude specific dates (holidays)

435

Recurrence.exclude_dates(

436

date(2024, 2, 19), # Presidents Day

437

date(2024, 5, 27), # Memorial Day

438

date(2024, 7, 4), # Independence Day

439

date(2024, 9, 2), # Labor Day

440

date(2024, 11, 28) # Thanksgiving week

441

)

442

]

443

)

444

gc.add_event(weekly_with_exceptions)

445

```

446

447

### Adding Specific Dates to Recurrence

448

449

```python

450

from gcsa.recurrence import Recurrence, WEEKLY, FRIDAY

451

from gcsa.event import Event

452

from datetime import datetime, date

453

454

# Regular weekly meeting plus additional dates

455

meeting_with_extras = Event(

456

summary="Team Sync",

457

start=datetime(2024, 1, 5, 14, 0), # First Friday

458

end=datetime(2024, 1, 5, 15, 0),

459

recurrence=[

460

# Every Friday

461

Recurrence.rule(freq=WEEKLY, by_weekday=FRIDAY),

462

463

# Add extra meeting dates

464

Recurrence.dates(

465

date(2024, 2, 14), # Special Valentine's Day meeting

466

date(2024, 3, 17), # St. Patrick's Day meeting

467

date(2024, 4, 1) # April Fool's Day meeting

468

)

469

]

470

)

471

gc.add_event(meeting_with_extras)

472

```

473

474

### Time-Specific Recurring Patterns

475

476

```python

477

from gcsa.recurrence import Recurrence, DAILY

478

from gcsa.event import Event

479

from datetime import datetime, time

480

481

# Multiple daily occurrences

482

daily_medication = Event(

483

summary="Medication Reminder",

484

start=datetime(2024, 1, 15, 8, 0),

485

end=datetime(2024, 1, 15, 8, 5),

486

recurrence=[

487

Recurrence.rule(

488

freq=DAILY,

489

by_hour=[8, 14, 20], # 8 AM, 2 PM, 8 PM

490

count=90 # 30 days × 3 times daily

491

)

492

]

493

)

494

gc.add_event(daily_medication)

495

496

# Hourly reminders during work hours

497

hourly_standup = Event(

498

summary="Hourly Check-in",

499

start=datetime(2024, 1, 15, 9, 0),

500

end=datetime(2024, 1, 15, 9, 5),

501

recurrence=[

502

Recurrence.rule(

503

freq=HOURLY,

504

by_weekday=[MO, TU, WE, TH, FR], # Weekdays only

505

by_hour=list(range(9, 17)), # 9 AM to 4 PM

506

until=datetime(2024, 12, 31)

507

)

508

]

509

)

510

gc.add_event(hourly_standup)

511

```

512

513

### Working with Duration

514

515

```python

516

from gcsa.recurrence import Duration

517

from gcsa.event import Event

518

from datetime import datetime

519

520

# Event with duration-based recurrence (less common)

521

duration = Duration(h=2, m=30) # 2 hours 30 minutes

522

523

# Note: Duration is mainly used for period-based RDATE entries

524

workshop_series = Event(

525

summary="Workshop Series",

526

start=datetime(2024, 2, 1, 9, 0),

527

end=datetime(2024, 2, 1, 12, 0),

528

recurrence=[

529

# Include specific periods with durations

530

Recurrence.periods(

531

(datetime(2024, 2, 1, 9, 0), datetime(2024, 2, 1, 12, 0)),

532

(datetime(2024, 2, 8, 9, 0), datetime(2024, 2, 8, 12, 0)),

533

(datetime(2024, 2, 15, 9, 0), datetime(2024, 2, 15, 12, 0))

534

)

535

]

536

)

537

gc.add_event(workshop_series)

538

```

539

540

### Week Start Configuration

541

542

```python

543

from gcsa.recurrence import Recurrence, WEEKLY, MONDAY, FRIDAY

544

545

# Specify different week start (Monday instead of Sunday)

546

weekly_meeting = Event(

547

summary="Weekly Planning",

548

start=datetime(2024, 1, 15, 9, 0),

549

end=datetime(2024, 1, 15, 10, 0),

550

recurrence=[

551

Recurrence.rule(

552

freq=WEEKLY,

553

by_weekday=FRIDAY,

554

week_start=MONDAY, # Week starts on Monday

555

count=26

556

)

557

]

558

)

559

gc.add_event(weekly_meeting)

560

```

561

562

### Business Day Patterns

563

564

```python

565

from gcsa.recurrence import Recurrence, WEEKLY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY

566

567

# Every business day (Monday through Friday)

568

daily_briefing = Event(

569

summary="Daily Team Briefing",

570

start=datetime(2024, 1, 15, 8, 30),

571

end=datetime(2024, 1, 15, 8, 45),

572

recurrence=[

573

Recurrence.rule(

574

freq=WEEKLY,

575

by_weekday=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY],

576

until=datetime(2024, 12, 31)

577

)

578

]

579

)

580

gc.add_event(daily_briefing)

581

582

# First business day of each month

583

monthly_report = Event(

584

summary="Monthly Report Due",

585

start=datetime(2024, 2, 1, 9, 0), # First business day of Feb

586

end=datetime(2024, 2, 1, 9, 30),

587

recurrence=[

588

Recurrence.rule(

589

freq=MONTHLY,

590

by_weekday=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY],

591

by_set_pos=1 # First weekday occurrence

592

)

593

]

594

)

595

gc.add_event(monthly_report)

596

```

597

598

### Error Handling for Recurrence

599

600

```python

601

from gcsa.recurrence import Recurrence, DAILY, WEEKLY

602

from gcsa.event import Event

603

from datetime import datetime

604

605

try:

606

# Invalid recurrence rule (count and until cannot both be specified)

607

invalid_event = Event(

608

summary="Invalid Recurrence",

609

start=datetime(2024, 1, 15, 10, 0),

610

end=datetime(2024, 1, 15, 11, 0),

611

recurrence=[

612

Recurrence.rule(

613

freq=DAILY,

614

count=30, # Count specified

615

until=datetime(2024, 6, 15) # Until also specified - invalid!

616

)

617

]

618

)

619

gc.add_event(invalid_event)

620

except Exception as e:

621

print(f"Recurrence error: {e}")

622

623

# Correct approach - use either count or until, not both

624

valid_event = Event(

625

summary="Valid Recurrence",

626

start=datetime(2024, 1, 15, 10, 0),

627

end=datetime(2024, 1, 15, 11, 0),

628

recurrence=[

629

Recurrence.rule(freq=DAILY, count=30) # Only count

630

]

631

)

632

gc.add_event(valid_event)

633

```

634

635

The Recurrence class provides comprehensive support for creating complex recurring event patterns using the standard RRULE format. It supports all common scheduling scenarios from simple daily meetings to complex business rules with exceptions and custom intervals.