CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-gcsa

Simple API for Google Calendar management

Pending
Overview
Eval results
Files

recurrence.mddocs/

Recurrence and Scheduling

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.

Package Information

from gcsa.recurrence import (
    Recurrence, Duration,
    SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY,
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY,
    SU, MO, TU, WE, TH, FR, SA,
    DEFAULT_WEEK_START
)

Recurrence Class

Basic Recurrence Rules

class Recurrence:
    @staticmethod
    def rule(
        freq,
        until = None,
        count = None, 
        interval = None,
        by_month = None,
        by_month_day = None,
        by_year_day = None,
        by_week_no = None,
        by_weekday = None,
        by_hour = None,
        by_minute = None,
        by_second = None,
        by_set_pos = None,
        week_start = None
    ):
        """
        Create a recurrence rule (RRULE) string.
        
        :param freq: Frequency of recurrence (SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY)
        :param until: End date/time for recurrence (datetime object)
        :param count: Number of occurrences (int)
        :param interval: Interval between occurrences (int, default=1)
        :param by_month: Month(s) for recurrence (1-12, list or int)
        :param by_month_day: Day(s) of month for recurrence (1-31, -31 to -1, list or int)
        :param by_year_day: Day(s) of year for recurrence (1-366, -366 to -1, list or int)
        :param by_week_no: Week number(s) for recurrence (1-53, -53 to -1, list or int)
        :param by_weekday: Weekday(s) for recurrence (SU-SA, list or string)
        :param by_hour: Hour(s) for recurrence (0-23, list or int)
        :param by_minute: Minute(s) for recurrence (0-59, list or int)
        :param by_second: Second(s) for recurrence (0-59, list or int)
        :param by_set_pos: Position(s) in set (1-366, -366 to -1, list or int)
        :param week_start: First day of week (SU-SA, default=SU)
        :return: RRULE string
        """

Exception Rules and Dates

@staticmethod
def exclude_rule(
    freq,
    until = None,
    count = None,
    interval = None,
    by_month = None,
    by_month_day = None,
    by_year_day = None,
    by_week_no = None,
    by_weekday = None,
    by_hour = None,
    by_minute = None,
    by_second = None,
    by_set_pos = None,
    week_start = None
):
    """
    Create an exception rule (EXRULE) string to exclude occurrences.
    
    Parameters same as rule() method.
    :return: EXRULE string
    """

@staticmethod
def dates(*dates):
    """
    Convert dates to RDATE format for including specific dates.
    
    :param dates: Date objects to include
    :return: RDATE string
    """

@staticmethod
def times(*datetimes):
    """
    Convert datetimes to RDATE format for including specific times.
    
    :param datetimes: Datetime objects to include
    :return: RDATE string
    """

@staticmethod
def periods(*periods):
    """
    Convert periods to RDATE format for including specific periods.
    
    :param periods: Period tuples (start, end) to include
    :return: RDATE string
    """

@staticmethod
def exclude_dates(*dates):
    """
    Convert dates to EXDATE format for excluding specific dates.
    
    :param dates: Date objects to exclude
    :return: EXDATE string
    """

@staticmethod
def exclude_times(*datetimes):
    """
    Convert datetimes to EXDATE format for excluding specific times.
    
    :param datetimes: Datetime objects to exclude
    :return: EXDATE string
    """

@staticmethod
def exclude_periods(*periods):
    """
    Convert periods to EXDATE format for excluding specific periods.
    
    :param periods: Period tuples (start, end) to exclude
    :return: EXDATE string
    """

Duration Class

class Duration:
    def __init__(
        self,
        w = None,  # weeks
        d = None,  # days
        h = None,  # hours
        m = None,  # minutes
        s = None   # seconds
    ):
        """
        Create a duration for use in recurrence rules.
        
        :param w: Number of weeks
        :param d: Number of days
        :param h: Number of hours
        :param m: Number of minutes
        :param s: Number of seconds
        """

Frequency Constants

# Recurrence frequency options
SECONDLY = "SECONDLY"    # Every second
MINUTELY = "MINUTELY"    # Every minute
HOURLY = "HOURLY"        # Every hour
DAILY = "DAILY"          # Every day
WEEKLY = "WEEKLY"        # Every week
MONTHLY = "MONTHLY"      # Every month
YEARLY = "YEARLY"        # Every year

Weekday Constants

# Day constants for recurrence rules
SUNDAY = SU = "SU"       # Sunday
MONDAY = MO = "MO"       # Monday
TUESDAY = TU = "TU"      # Tuesday
WEDNESDAY = WE = "WE"    # Wednesday
THURSDAY = TH = "TH"     # Thursday
FRIDAY = FR = "FR"       # Friday
SATURDAY = SA = "SA"     # Saturday

# Default week start
DEFAULT_WEEK_START = SUNDAY

Basic Usage Examples

Simple Recurring Events

from gcsa.google_calendar import GoogleCalendar
from gcsa.event import Event
from gcsa.recurrence import Recurrence, DAILY, WEEKLY, MONTHLY
from datetime import datetime, date

gc = GoogleCalendar()

# Daily recurring event
daily_standup = Event(
    summary="Daily Standup",
    start=datetime(2024, 1, 15, 9, 0),
    end=datetime(2024, 1, 15, 9, 15),
    recurrence=[
        Recurrence.rule(freq=DAILY, count=30)  # 30 occurrences
    ]
)
gc.add_event(daily_standup)

# Weekly recurring event
weekly_meeting = Event(
    summary="Team Meeting", 
    start=datetime(2024, 1, 15, 10, 0),
    end=datetime(2024, 1, 15, 11, 0),
    recurrence=[
        Recurrence.rule(freq=WEEKLY, until=datetime(2024, 6, 15))  # Until June 15
    ]
)
gc.add_event(weekly_meeting)

# Monthly recurring event
monthly_review = Event(
    summary="Monthly Review",
    start=datetime(2024, 1, 1, 14, 0),
    end=datetime(2024, 1, 1, 15, 0), 
    recurrence=[
        Recurrence.rule(freq=MONTHLY, interval=1, count=12)  # Monthly for 1 year
    ]
)
gc.add_event(monthly_review)

Weekday-Specific Recurring Events

from gcsa.recurrence import Recurrence, WEEKLY, MONDAY, WEDNESDAY, FRIDAY
from gcsa.event import Event
from datetime import datetime

# Every Monday, Wednesday, and Friday
mwf_workout = Event(
    summary="Workout Session",
    start=datetime(2024, 1, 15, 7, 0),  # Start on a Monday
    end=datetime(2024, 1, 15, 8, 0),
    recurrence=[
        Recurrence.rule(
            freq=WEEKLY,
            by_weekday=[MONDAY, WEDNESDAY, FRIDAY],
            count=36  # 12 weeks × 3 days
        )
    ]
)
gc.add_event(mwf_workout)

# Every Tuesday and Thursday  
tt_meetings = Event(
    summary="Client Check-in",
    start=datetime(2024, 1, 16, 15, 0),  # Start on a Tuesday
    end=datetime(2024, 1, 16, 15, 30),
    recurrence=[
        Recurrence.rule(
            freq=WEEKLY,
            by_weekday=[TU, TH],  # Can use short forms
            until=datetime(2024, 12, 31)
        )
    ]
)
gc.add_event(tt_meetings)

Advanced Monthly Patterns

from gcsa.recurrence import Recurrence, MONTHLY, FRIDAY
from gcsa.event import Event
from datetime import datetime

# First Friday of every month
first_friday = Event(
    summary="First Friday Drinks",
    start=datetime(2024, 2, 2, 17, 0),  # First Friday in Feb
    end=datetime(2024, 2, 2, 19, 0),
    recurrence=[
        Recurrence.rule(
            freq=MONTHLY,
            by_weekday=FRIDAY,
            by_set_pos=1  # First occurrence
        )
    ]
)
gc.add_event(first_friday)

# Last day of every month
month_end_report = Event(
    summary="Month End Report Due",
    start=datetime(2024, 1, 31, 17, 0),
    end=datetime(2024, 1, 31, 17, 30),
    recurrence=[
        Recurrence.rule(
            freq=MONTHLY,
            by_month_day=-1  # Last day of month
        )
    ]
)
gc.add_event(month_end_report)

# 15th of every month
mid_month_review = Event(
    summary="Mid-Month Review",
    start=datetime(2024, 1, 15, 10, 0),
    end=datetime(2024, 1, 15, 11, 0),
    recurrence=[
        Recurrence.rule(
            freq=MONTHLY,
            by_month_day=15,
            count=12
        )
    ]
)
gc.add_event(mid_month_review)

Yearly Recurring Events

from gcsa.recurrence import Recurrence, YEARLY
from gcsa.event import Event
from datetime import datetime

# Annual company retreat
annual_retreat = Event(
    summary="Annual Company Retreat",
    start=datetime(2024, 6, 15, 9, 0),
    end=datetime(2024, 6, 16, 17, 0),  # 2-day event
    recurrence=[
        Recurrence.rule(
            freq=YEARLY,
            by_month=6,        # June
            by_month_day=15,   # 15th
            count=5            # Next 5 years
        )
    ]
)
gc.add_event(annual_retreat)

# Birthday recurring event
birthday = Event(
    summary="John's Birthday",
    start=date(2024, 3, 10),
    end=date(2024, 3, 11),
    recurrence=[
        Recurrence.rule(freq=YEARLY)  # Every year forever
    ]
)
gc.add_event(birthday)

Complex Intervals and Patterns

from gcsa.recurrence import Recurrence, DAILY, WEEKLY, MONTHLY
from gcsa.event import Event
from datetime import datetime

# Every other day
every_other_day = Event(
    summary="Alternate Day Workout",
    start=datetime(2024, 1, 15, 6, 0),
    end=datetime(2024, 1, 15, 7, 0),
    recurrence=[
        Recurrence.rule(
            freq=DAILY,
            interval=2,  # Every 2 days
            count=50
        )
    ]
)
gc.add_event(every_other_day)

# Every 3 weeks
tri_weekly = Event(
    summary="Tri-weekly Sprint Planning",
    start=datetime(2024, 1, 15, 9, 0),
    end=datetime(2024, 1, 15, 10, 30),
    recurrence=[
        Recurrence.rule(
            freq=WEEKLY,
            interval=3,  # Every 3 weeks
            by_weekday=MONDAY
        )
    ]
)
gc.add_event(tri_weekly)

# Quarterly meetings (every 3 months)
quarterly = Event(
    summary="Quarterly Business Review",
    start=datetime(2024, 1, 31, 14, 0),
    end=datetime(2024, 1, 31, 16, 0),
    recurrence=[
        Recurrence.rule(
            freq=MONTHLY,
            interval=3,      # Every 3 months
            by_month_day=-1  # Last day of quarter-ending month
        )
    ]
)
gc.add_event(quarterly)

Recurring Events with Exceptions

from gcsa.recurrence import Recurrence, WEEKLY, MONDAY
from gcsa.event import Event
from datetime import datetime, date

# Weekly meeting with holiday exceptions
weekly_with_exceptions = Event(
    summary="Weekly Staff Meeting",
    start=datetime(2024, 1, 8, 10, 0),
    end=datetime(2024, 1, 8, 11, 0),
    recurrence=[
        # Main rule: every Monday
        Recurrence.rule(freq=WEEKLY, by_weekday=MONDAY, count=52),
        
        # Exclude specific dates (holidays)
        Recurrence.exclude_dates(
            date(2024, 2, 19),  # Presidents Day
            date(2024, 5, 27),  # Memorial Day
            date(2024, 7, 4),   # Independence Day
            date(2024, 9, 2),   # Labor Day
            date(2024, 11, 28)  # Thanksgiving week
        )
    ]
)
gc.add_event(weekly_with_exceptions)

Adding Specific Dates to Recurrence

from gcsa.recurrence import Recurrence, WEEKLY, FRIDAY
from gcsa.event import Event
from datetime import datetime, date

# Regular weekly meeting plus additional dates
meeting_with_extras = Event(
    summary="Team Sync",
    start=datetime(2024, 1, 5, 14, 0),  # First Friday
    end=datetime(2024, 1, 5, 15, 0),
    recurrence=[
        # Every Friday
        Recurrence.rule(freq=WEEKLY, by_weekday=FRIDAY),
        
        # Add extra meeting dates
        Recurrence.dates(
            date(2024, 2, 14),  # Special Valentine's Day meeting
            date(2024, 3, 17),  # St. Patrick's Day meeting
            date(2024, 4, 1)    # April Fool's Day meeting
        )
    ]
)
gc.add_event(meeting_with_extras)

Time-Specific Recurring Patterns

from gcsa.recurrence import Recurrence, DAILY
from gcsa.event import Event
from datetime import datetime, time

# Multiple daily occurrences
daily_medication = Event(
    summary="Medication Reminder",
    start=datetime(2024, 1, 15, 8, 0),
    end=datetime(2024, 1, 15, 8, 5),
    recurrence=[
        Recurrence.rule(
            freq=DAILY,
            by_hour=[8, 14, 20],  # 8 AM, 2 PM, 8 PM
            count=90  # 30 days × 3 times daily
        )
    ]
)
gc.add_event(daily_medication)

# Hourly reminders during work hours
hourly_standup = Event(
    summary="Hourly Check-in",
    start=datetime(2024, 1, 15, 9, 0),
    end=datetime(2024, 1, 15, 9, 5),
    recurrence=[
        Recurrence.rule(
            freq=HOURLY,
            by_weekday=[MO, TU, WE, TH, FR],  # Weekdays only
            by_hour=list(range(9, 17)),       # 9 AM to 4 PM
            until=datetime(2024, 12, 31)
        )
    ]
)
gc.add_event(hourly_standup)

Working with Duration

from gcsa.recurrence import Duration
from gcsa.event import Event
from datetime import datetime

# Event with duration-based recurrence (less common)
duration = Duration(h=2, m=30)  # 2 hours 30 minutes

# Note: Duration is mainly used for period-based RDATE entries
workshop_series = Event(
    summary="Workshop Series",
    start=datetime(2024, 2, 1, 9, 0),
    end=datetime(2024, 2, 1, 12, 0),
    recurrence=[
        # Include specific periods with durations
        Recurrence.periods(
            (datetime(2024, 2, 1, 9, 0), datetime(2024, 2, 1, 12, 0)),
            (datetime(2024, 2, 8, 9, 0), datetime(2024, 2, 8, 12, 0)),
            (datetime(2024, 2, 15, 9, 0), datetime(2024, 2, 15, 12, 0))
        )
    ]
)
gc.add_event(workshop_series)

Week Start Configuration

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

# Specify different week start (Monday instead of Sunday)
weekly_meeting = Event(
    summary="Weekly Planning",
    start=datetime(2024, 1, 15, 9, 0),
    end=datetime(2024, 1, 15, 10, 0),
    recurrence=[
        Recurrence.rule(
            freq=WEEKLY,
            by_weekday=FRIDAY,
            week_start=MONDAY,  # Week starts on Monday
            count=26
        )
    ]
)
gc.add_event(weekly_meeting)

Business Day Patterns

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

# Every business day (Monday through Friday)
daily_briefing = Event(
    summary="Daily Team Briefing",
    start=datetime(2024, 1, 15, 8, 30),
    end=datetime(2024, 1, 15, 8, 45),
    recurrence=[
        Recurrence.rule(
            freq=WEEKLY,
            by_weekday=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY],
            until=datetime(2024, 12, 31)
        )
    ]
)
gc.add_event(daily_briefing)

# First business day of each month
monthly_report = Event(
    summary="Monthly Report Due",
    start=datetime(2024, 2, 1, 9, 0),  # First business day of Feb
    end=datetime(2024, 2, 1, 9, 30),
    recurrence=[
        Recurrence.rule(
            freq=MONTHLY,
            by_weekday=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY],
            by_set_pos=1  # First weekday occurrence
        )
    ]
)
gc.add_event(monthly_report)

Error Handling for Recurrence

from gcsa.recurrence import Recurrence, DAILY, WEEKLY
from gcsa.event import Event
from datetime import datetime

try:
    # Invalid recurrence rule (count and until cannot both be specified)
    invalid_event = Event(
        summary="Invalid Recurrence",
        start=datetime(2024, 1, 15, 10, 0),
        end=datetime(2024, 1, 15, 11, 0),
        recurrence=[
            Recurrence.rule(
                freq=DAILY,
                count=30,  # Count specified
                until=datetime(2024, 6, 15)  # Until also specified - invalid!
            )
        ]
    )
    gc.add_event(invalid_event)
except Exception as e:
    print(f"Recurrence error: {e}")

# Correct approach - use either count or until, not both
valid_event = Event(
    summary="Valid Recurrence",
    start=datetime(2024, 1, 15, 10, 0),
    end=datetime(2024, 1, 15, 11, 0),
    recurrence=[
        Recurrence.rule(freq=DAILY, count=30)  # Only count
    ]
)
gc.add_event(valid_event)

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.

Install with Tessl CLI

npx tessl i tessl/pypi-gcsa

docs

access-control.md

attendees.md

calendars.md

conferences.md

core-operations.md

events.md

free-busy.md

index.md

recurrence.md

reminders.md

tile.json