API Reference#

This is the public API for this library.

Core functionality#

This is the core of the functionality of the library.

The first step is to customize which components to query with recurring_ical_events.of().

recurring_ical_events.of(a_calendar, keep_recurrence_attributes=False, components=('VEVENT',), skip_bad_series=False, calendar_query=CalendarQuery)[source]#

Create a query for recurring components in a_calendar.

If the argument is a calendar, this will also correct times according to X-WR-TIMEZONE.

Parameters:
  • a_calendar (icalendar.cal.Component) – an icalendar.cal.calendar.Calendar component like icalendar.cal.calendar.Calendar.

  • keep_recurrence_attributes – Whether to keep attributes that are only used to calculate the recurrence (RDATE, EXDATE, RRULE).

  • components (recurring_ical_events.query.T_COMPONENTS) – A list of component type names of which the recurrences should be returned. This can also be instances of SelectComponents. Examples: ("VEVENT", "VTODO", "VJOURNAL", "VALARM")

  • skip_bad_series (bool) – Whether to skip series of components that contain errors. You can use CalendarQuery.suppressed_errors to specify which errors to skip.

  • calendar_query (type[CalendarQuery]) – The CalendarQuery class to use.

Return type:

CalendarQuery

Query#

of() returns a recurring_ical_events.CalendarQuery object, which can be used to query the calendar. For the most common cases, you do not need to look any further.

class recurring_ical_events.CalendarQuery(calendar, keep_recurrence_attributes=False, components=('VEVENT',), skip_bad_series=False)[source]#

Query a calendar for occurrences.

Functions like at(), between() andm after() can be used to query the selected components. If any malformed icalendar information is found, an InvalidCalendar exception is raised. For other bad arguments, you should expect a ValueError.

suppressed_errors#

a list of errors to suppress when skip_bad_series is True

after(earliest_end)[source]#

Iterate over components happening during or after earliest_end.

Parameters:

earliest_end (recurring_ical_events.types.DateArgument) – A date specification. See to_datetime(). Anything happening during or after earliest_end is returned in the order of start time.

Return type:

Generator[icalendar.cal.Component, None, None]

all()[source]#

Generate all Components.

The Components are sorted from the first to the last Occurrence. Calendars can contain millions of Occurrences. This iterates safely across all of them.

Return type:

Generator[icalendar.cal.Component, None, None]

at(date)[source]#

Return all events within the next 24 hours of starting at the given day.

Parameters:

date (recurring_ical_events.types.DateArgument) – A date specification, see to_datetime().

This is translated to between() in the following way:

  • A year returns all occurrences within that year.

    Example: (2019,), 2019

  • A month returns all occurrences within that month.

    Example: (2019, 1)

  • A day returns all occurrences within that day.

    Examples:

    • (2019, 1, 19)

    • datetime.date(2019, 1, 19)

    • "20190101"

  • An hour returns all occurrences within that hour.

    Example: (2019, 1, 19, 1)

  • A minute returns all occurrences within that minute.

    Example: (2019, 1, 19, 13, 30 )

  • A second returns all occurrences at that exact second.

    Examples:

    • (2019, 1, 19, 13, 30, 59)

    • datetime.datetime(2019, 1, 19, 13, 30, 59)

    • datetime.datetime(2019, 1, 19, tzinfo=datetime.timezone.utc),

    • datetime.datetime(2019, 1, 19, 13, 30, 59, tzinfo=ZoneInfo('Europe/London'))

    • "20190119T133059Z"

between(start, stop)[source]#

Return events at a time between start (inclusive) and end (inclusive)

Parameters:

Warning

If you pass a datetime.datetime to both start and stop, make sure the datetime.datetime.tzinfo is the same.

count()[source]#

Return the amount of recurring components in this calendar.

Warning

Do not use this in production as it generates all occurrences.

Return type:

int

property first: icalendar.cal.Component#

Return the first recurring component in this calendar.

Returns:

The first recurring component in this calendar.

Raises:

IndexError – if the calendar is empty

paginate(page_size, earliest_end=None, latest_start=None, next_page_id='')[source]#

Return pages for pagination.

Parameters:
  • page_size (int) – the number of components per page

  • earliest_end (Optional[recurring_ical_events.types.DateArgument]) – the start of the first page All components occur after this date. See to_datetime() for possible values.

  • latest_start (Optional[recurring_ical_events.types.DateArgument]) – the end of the last page All components occur before this date. See to_datetime() for possible values.

  • next_page_id (str) – The id of the next page. This is optional for the first page. These are safe to pass outside of the application and back in.

Return type:

Pages

static to_datetime(date)[source]#

Convert date inputs of various sorts into a datetime object.

Parameters:

date (recurring_ical_events.types.DateArgument) – A date specification.

Date Specification:

  • a year like (2019,) or 2019 (int)

  • a month like (2019, 1) for January of 2019

  • a day like (2019, 1, 19) for the first of January 2019

  • a day with hours, (2019, 1, 19, 1)

  • a day with minutes, (2019, 1, 19, 13, 30 )

  • a day with seconds, (2019, 1, 19, 13, 30, 59)

  • a datetime.datetime or datetime.date

  • a str in the format yyyymmdd

  • a str in the format yyyymmddThhmmssZ

list from at() and between()#

The result of both recurring_ical_events.CalendarQuery.between() and recurring_ical_events.CalendarQuery.at() is a list of icalendar.cal.component.Component objects like icalendar.cal.event.Event. By default, all attributes of the event with repetitions are copied, like UID and SUMMARY. However, these attributes may differ from the source event:

  • DTSTART which is the start of the event instance. (always present)

  • DTEND which is the end of the event instance. (always present)

  • RDATE, EXDATE, RRULE are the rules to create event repetitions. They are not included in repeated events, see Issue 23. To change this, use of(calendar, keep_recurrence_attributes=True).

Generator from after() and all()#

If the resulting components are ordered when recurring_ical_events.CalendarQuery.after() or recurring_ical_events.CalendarQuery.all() is used. The result is an iterator that returns the events in order.

for event in recurring_ical_events.of(an_icalendar_object).after(datetime.datetime.now()):
    print(event["DTSTART"]) # The start is ordered

Timezones and floating time#

This library makes a distinction between floating time and times with timezones.

Examples:

  • Event 1 happes at 12:00 in Singapore and event 2 on the same day at 12:00 in New York.

    • If you query that day without timezone, you will get both events.

    • If you query 12:00 - 13:00 without timezone, you will get both events.

    • If you query 12:00 - 13:00 in Asia/Singapore, you will only get event 1.

    • If you query 12:00 - 13:00 in America/New_York, you will only get event 2.

  • If an event happens at night in floating time (without timezone) and you query that day it will appear regardless of the timezone of the query. Which is at different times in different timezones.

  • icalendar.cal.alarm.Alarm has a TRIGGER which is in UTC. The timezone to compute that for alarms relative to floating events will be taken from the start and stop arguments.

Pagination#

For ease of use, pagination has been introduced. These are the pages returned by the query.

Pagination for recurring ical events.

See niccokunzmann/python-recurring-ical-events#211

class recurring_ical_events.pages.Page(components, next_page_id='')[source]#

One page in a series of pages.

Examples

Check if the page has components.

if page:
    print(f"We have {len(page)} components.")

Go though the components:

for component in page:
    print(component)
property components: list[TypeAliasForwardRef('icalendar.cal.Component')]#

All the components of this page.

has_next_page()[source]#

Wether there is a page following this one.

Return type:

bool

is_last()[source]#

Wether this is the last page and there is no other page following.

Return type:

bool

property next_page_id: str#

The id of the next page or ''.

class recurring_ical_events.pages.Pages(occurrence_iterator, size, stop=None, keep_recurrence_attributes=False)[source]#

A pagination configuration to iterate over pages.

This is an Iterator that returns Page objects.

generate_next_page()[source]#

Generate the next page.

In contrast to next(pages), this does not raise StopIteration. But it works the same: the next page is generated and returned. The last page is empty.

Return type:

Page

property size: int#

The maximum number of components per page.

Complete API#

Calculate repetitions of icalendar components.

class recurring_ical_events.AbsoluteAlarmAdapter(alarm, parent)[source]#

Bases: ComponentAdapter

Adapter for absolute alarms.

class recurring_ical_events.AbsoluteAlarmSeries[source]#

Bases: object

A series of absolute alarms.

add(alarm, parent)[source]#

Add an absolute alarm with a parent component.

between(span_start, span_stop)[source]#

Components between the start (inclusive) and end (exclusive).

The result does not need to be ordered.

Return type:

Generator[Occurrence, None, None]

is_empty()[source]#

Whether this series is empty.

Return type:

bool

occurrence(dt, alarm, parent)[source]#

Create a new occurrence.

Return type:

Occurrence

class recurring_ical_events.AlarmOccurrence(trigger, alarm, parent)[source]#

Bases: Occurrence

Adapter for absolute alarms.

as_component(keep_recurrence_attributes)[source]#

Return the alarm’s parent as a modified component.

property id: recurring_ical_events.occurrence.OccurrenceID#

The id of the component.

class recurring_ical_events.AlarmSeriesRelativeToEnd(alarm, series)[source]#

Bases: AlarmSeriesRelativeToStart

A series of alarms relative to the start of a component.

between(span_start, span_stop)[source]#

Components between the start (inclusive) and end (exclusive).

The result does not need to be ordered.

occurrence(offset, alarm, parent)[source]#

Create a new occurrence.

Return type:

Occurrence

class recurring_ical_events.AlarmSeriesRelativeToStart(alarm, series)[source]#

Bases: object

A series of alarms relative to the start of a component.

between(span_start, span_stop)[source]#

Components between the start (inclusive) and end (exclusive).

The result does not need to be ordered.

Return type:

Generator[Occurrence, None, None]

occurrence(offset, alarm, parent)[source]#

Create a new occurrence.

Return type:

Occurrence

class recurring_ical_events.Alarms(parents=(EventAdapter, TodoAdapter))[source]#

Bases: SelectComponents

Select alarms and find their times.

By default, alarms from TODOs and events are collected. You can use this to change which alarms are collected:

Alarms((EventAdapter,)) Alarms((TodoAdapter,))

collect_parent_series_from(source, suppress_errors)[source]#

Collect the parent components of alarms.

Return type:

Sequence[Series]

collect_series_from(source, suppress_errors)[source]#

Collect all TODOs and Alarms from VEVENTs and VTODOs.

Return type:

Sequence[Series]

suppress_errors - a list of errors that should be suppressed.

A Series of events with such an error is removed from all results.

static component_name()[source]#

The name of the component we calculate.

class recurring_ical_events.AllKnownComponents(series=Series, occurrence=Occurrence, collector=ComponentsWithName)[source]#

Bases: SelectComponents

Group all known components into series.

collect_series_from(source, suppress_errors)[source]#

Collect the components from the source groups into a series.

Return type:

Sequence[Series]

property names: list[str]#

Return the names of the components to collect.

exception recurring_ical_events.BadRuleStringFormat(message, rule)[source]#

Bases: InvalidCalendar

An iCal rule string is badly formatted.

property rule: str#

The malformed rule string

class recurring_ical_events.ComponentAdapter(component)[source]#

Bases: ABC

A unified interface to work with icalendar components.

property alarms: list[Alarm]#

The alarms in this component.

as_component(start=None, stop=None, keep_recurrence_attributes=True)[source]#

Create a shallow copy of the source event and modify some attributes.

classmethod collect_series_from(source, suppress_errors)[source]#

Collect all components for this adapter.

This is a shortcut.

Return type:

Sequence[Series]

abstractmethod static component_name()[source]#

The icalendar component name.

Return type:

str

property duration: datetime.timedelta#

The duration of the component.

property end: recurring_ical_events.types.Time#

The end time.

property end_property: str | None#

The name of the end property.

property exdates: list[TypeAliasForwardRef('recurring_ical_events.types.Time')]#

A list of exdates.

property extend_query_span_by: tuple[datetime.timedelta, datetime.timedelta]#

Calculate how much we extend the query span.

If an event is long, we need to extend the query span by the event’s duration. If an event has moved, we need to make sure that that is included, too.

This is so that the RECURRENCE-ID falls within the modified span. Imagine if the span is exactly a second. How much would we need to query forward and backward to capture the recurrence id?

Returns two positive spans: (subtract_from_start, add_to_stop)

has_recurrence_rules()[source]#

Whether this has generation rules present.

is_in_span(span_start, span_stop)[source]#

Return whether the component is in the span.

Return type:

bool

is_modification()[source]#

Whether the adapter is a modification.

Return type:

bool

property move_recurrences_by: datetime.timedelta#

Occurrences of this component should be moved by this amount.

Usually, the occurrence starts at the new start time. However, if we have a RANGE=THISANDFUTURE, we need to move the occurrence.

RFC 5545:

When the given recurrence instance is rescheduled, all subsequent instances are also rescheduled by the same time difference. For instance, if the given recurrence instance is rescheduled to start 2 hours later, then all subsequent instances are also rescheduled 2 hours later. Similarly, if the duration of the given recurrence instance is modified, then all subsequence instances are also modified to have this same duration.

abstract property raw_end#

Return the start property of the component.

abstract property raw_start#

Return the start property of the component.

property rdates: list[TypeAliasForwardRef('recurring_ical_events.types.Time'), tuple[TypeAliasForwardRef('recurring_ical_events.types.Time'), TypeAliasForwardRef('recurring_ical_events.types.Time')]]#

A list of rdates, possibly a period.

property recurrence_ids: recurring_ical_events.types.RecurrenceIDs#

The recurrence ids of the component that might be used to identify it.

property rrules: set[str]#

A list of rrules of this component.

property sequence: int#

The sequence in the history of modification.

The sequence is negative if none was found.

property span#

Return (start, end).

property start: recurring_ical_events.types.Time#

The start time.

property this_and_future: bool#

The recurrence ids has a thisand future range property

property uid: recurring_ical_events.types.UID#

The UID of a component.

UID is required by RFC5545. If the UID is absent, we use the Python ID.

class recurring_ical_events.ComponentsWithName(name, adapter=None, series=Series, occurrence=Occurrence)[source]#

Bases: SelectComponents

This is a component collecttion strategy.

Components can be collected in different ways. This class allows extension of the functionality by - subclassing to filter the resulting components - composition to combine collection behavior (see AllKnownComponents)

collect_series_from(source, suppress_errors)[source]#

Collect all components from the source component.

Return type:

Sequence[Series]

suppress_errors - a list of errors that should be suppressed.

A Series of events with such an error is removed from all results.

class recurring_ical_events.EventAdapter(component)[source]#

Bases: ComponentAdapter

An icalendar event adapter.

static component_name()[source]#

The icalendar component name.

Return type:

str

property end_property: str#

DTEND

property raw_end: recurring_ical_events.types.Time#

Yield DTEND or calculate the end of the event based on DTSTART and DURATION.

property raw_start: recurring_ical_events.types.Time#

Return DTSTART

exception recurring_ical_events.InvalidCalendar(message)[source]#

Bases: ValueError

Exception thrown for bad icalendar content.

property message: str#

The error message.

class recurring_ical_events.JournalAdapter(component)[source]#

Bases: ComponentAdapter

Apdater for journal entries.

static component_name()[source]#

The icalendar component name.

Return type:

str

property end_property: None#

There is no end property

property raw_end: date | datetime#

The end time is the same as the start.

property raw_start: date | datetime#

Return DTSTART if it set, do not panic if it’s not set.

class recurring_ical_events.Occurrence(adapter, start=None, end=None, sequence=-1)[source]#

Bases: object

A repetition of an event.

as_component(keep_recurrence_attributes)[source]#

Create a shallow copy of the source component and modify some attributes.

Return type:

icalendar.cal.Component

component_name()[source]#

The name of this component.

Return type:

str

has_alarm(alarm)[source]#

Wether this alarm is in this occurrence.

Return type:

bool

property id: recurring_ical_events.occurrence.OccurrenceID#

The id of the component.

is_in_span(span_start, span_stop)[source]#

Return whether the component is in the span.

Return type:

bool

property recurrence_ids: recurring_ical_events.types.RecurrenceIDs#

The recurrence ids.

property uid: str#

The UID of this occurrence.

exception recurring_ical_events.PeriodEndBeforeStart(message, start, end)[source]#

Bases: InvalidCalendar

An event or component starts before it ends.

property end: date | datetime#

The end of the component’s period.

property start: date | datetime#

The start of the component’s period.

class recurring_ical_events.SelectComponents[source]#

Bases: ABC

Abstract class to select components from a calendar.

abstractmethod collect_series_from(source, suppress_errors)[source]#

Collect all components from the source grouped together into a series.

Return type:

Sequence[Series]

suppress_errors - a list of errors that should be suppressed.

A Series of events with such an error is removed from all results.

static component_name()[source]#

The name of the component if there is only one.

class recurring_ical_events.Series(components)[source]#

Bases: object

Base class for components that result in a series of occurrences.

class NoRecurrence[source]#

Bases: object

A strategy to deal with not having a core with rrules.

rrule_between(span_start, span_stop)[source]#

No repetition.

Return type:

Generator[recurring_ical_events.types.Time, None, None]

class RecurrenceRules(core)[source]#

Bases: object

A strategy if we have an actual core with recurrences.

as_occurrence(start, stop, occurrence, core)[source]#

Return this as an occurrence at a specific time.

Return type:

Occurrence

property components: list[ComponentAdapter]#

The components in this recurrence calculation.

convert_to_original_type(date)[source]#

Convert a date back if this is possible.

Dates may get converted to datetimes to make calculations possible. This reverts the process where possible so that Repetitions end up with the type (date/datetime) that was specified in the icalendar component.

create_rule_with_start(rule_string)[source]#

Helper to create an rrule from a rule_string

The rrule is starting at the start of the component. Since the creation is a bit more complex, this function handles special cases.

Return type:

rrule

property extend_query_span_by: tuple[datetime.timedelta, datetime.timedelta]#

The extension of the time span we need for this component’s core.

make_all_dates_comparable()[source]#

Make sure we can use all dates with eachother.

Dates may be mixed and we have many of them. - date - datetime without timezone - datetime with timezone These three are not comparable but can be converted.

rrule_between(span_start, span_stop)[source]#

Recalculate the rrules so that minor mistakes are corrected.

Return type:

Generator[recurring_ical_events.types.Time, None, None]

rrulestr(rule_string)[source]#

Return an rrulestr with a start. This might fail.

Return type:

rrule

property sequence: int#

The sequence of the code component.

between(span_start, span_stop)[source]#

Components between the start (inclusive) and end (exclusive).

The result does not need to be ordered.

Return type:

Generator[Occurrence, None, None]

property components: list[ComponentAdapter]#

All the components in this sequence.

Components with the same UID might not occur if the SEQUENCE number suggests that they are obsolete.

compute_span_extension()[source]#

Compute how much to extend the span for the rrule to cover all events.

get_component_for_recurrence_id(recurrence_id)[source]#

Get the component which contains all information for the recurrence id.

This concerns this modifications that have RANGE=THISANDFUTURE set.

Return type:

ComponentAdapter

has_recurrence_id_in_rrule(modification)[source]#

Wether this occurrence ID is part of the RRULE.

Return type:

bool

occurrence(adapter, start=None, end=None)[source]#

A way to override the occurrence class.

rrule_between(span_start, span_stop)[source]#

Modify the rrule generation span and yield recurrences.

Return type:

Generator[recurring_ical_events.types.Time, None, None]

skip_core_modification(modification)[source]#

Wether to skip this occurrence.

See Issues: - niccokunzmann/python-recurring-ical-events#253 - niccokunzmann/python-recurring-ical-events#148 - niccokunzmann/python-recurring-ical-events#164

Return type:

bool

property this_and_future_components: Generator[ComponentAdapter, None, None]#

All components that influence future events.

property uid#

The UID that identifies this series.

class recurring_ical_events.TodoAdapter(component)[source]#

Bases: ComponentAdapter

Unified access to TODOs.

static component_name()[source]#

The icalendar component name.

Return type:

str

property end_property: str#

DUE

property raw_end: date | datetime#

Return DUE or DTSTART+DURATION or something

property raw_start: date | datetime#

Return DTSTART if it set, do not panic if it’s not set.

recurring_ical_events.example_calendar(name='')[source]#

Return an example calendar.

Parameters:

name (str) – The name of the example file.

Returns:

The parsed calendar example.

Return type:

icalendar.cal.Calendar

Type annotations.

recurring_ical_events.types.RecurrenceID#

alias of datetime

recurring_ical_events.types.Timestamp#

alias of float

recurring_ical_events.types.UID#

alias of str

class recurring_ical_events.OccurrenceID(name: str, uid: UID, recurrence_id: Time | None, start: Time)[source]#

The ID of a component’s occurrence to identify it clearly.

name#

The name of the component, e.g. “VEVENT”

uid#

The UID of the component.

recurrence_id#

The Recurrence-ID of the component in UTC but without tzinfo.

start#

The start of the component

to_string()[source]#

Return a string representation of this id.

Return type:

str

classmethod from_string(string_id)[source]#

Parse a string and return the component id.

Return type:

recurring_ical_events.occurrence.OccurrenceID

classmethod from_occurrence(name, uid, recurrence_ids, start)[source]#

Create a new OccurrenceID from the given values.

Parameters:
  • name (str) – The component name.

  • uid (str) – The UID string.

  • recurrence_ids (recurring_ical_events.types.RecurrenceIDs) – The recurrence ID tuple. This is expected as UTC with tzinfo being None.

  • start (recurring_ical_events.types.Time) – start time of the component either with or without timezone