[Pitch] `Calendar.RecurrenceRule`

Hi all,

I would like to pitch a new struct, Calendar.RecurrenceRule , that describes recurring events and calculates future recurrences. Please let me know if you have any questions/comments/thoughts!

Recurrence rules in Calendar

Introduction

This proposal introduces API for enumerating dates matching a specific recurrence rule, and a structure to represent recurrence rules.

Motivation

In a calendar, a recurrence rule is a set of rules describing how often a repeating event should occur. E.g. "Yearly", "Every 1st Saturday of the month", etc. Foundation owns the Calendar type, and as such it makes sense for recurrence rules to be implement alongside Calendar.

Proposed solution and example

We introduce struct Calendar.RecurrenceRule that describes how often an event should repeat. The structure models a subset of RRULE specified in:

  • RFC-5545 Internet Calendaring and Scheduling Core Object Specification (iCalendar), 3.3.10. Recurrence Rule [^rfc-5545]
  • RFC-7529 Non-Gregorian Recurrence Rules in the Internet Calendaring and Scheduling Core Object Specification (iCalendar) [^rfc-7529]

Here's a simple usage of RecurrenceRule. Assume that Date.now is 13 February 2024, 13:43.

var recurrence = Calendar.RecurrenceRule(calendar: .current, frequency: .weekly)
recurrence.weekdays = [.every(.tuesday), .every(.wednesday), .every(.thursday)]
for date in recurrence.recurrences(of: .now) {
    // 13 February 2024, 13:43 (Tuesday)
    // 14 February 2024, 13:43 (Wednesday)
    // 15 February 2024, 13:43 (Thursday)
    // 20 February 2024, 13:43 (Tuesday)
    // 21 February 2024, 13:43 (Wednesday)
    // ...
}

I have posted the full pitch including the detailed design as a pull request on the swift-foundation repository. Check out the full pitch to read more info about the proposed design.

6 Likes

While only tangentially related, one feature of calendars that we’ve been missing is to be able to specify a set of days to not be business days - e.g. for being able to calculate the number of business days between two days, or to calculate which calendar date a given date + a number of business days would be. One would want to specify that e.g. recurring days (as mentioned in this proposal) plus other specific (user specified) days should be excluded as business days.
Maybe I’m missing something, but this seems to be a missing part of the calendar API:s (concretely, we’d like to use it e.g, to calculate settlement dates for transactions and similar use cases).

2 Likes

As Joakim highlighted, we are interested in developing business calendar functionality for settlement calculations. A particularly tailored feature for our field would be the ability to create and manage trading calendars. These would detail the operating hours for exchanges, incorporating both standard closures (like weekends and the 1st of January) and partial closures. An example of the latter could be the Stockholm Exchange, where stocks from Denmark, Sweden, Finland, and Norway are traded. Each of these national segments has its own trading hours, impacting calculations related to the total trading hours between any two given points in time. Therefore, the system would account for regular trading intervals (typically Monday to Friday) and exceptions. For instance, in Sweden, trading hours are usually from 9 am to 5:30 pm, but on April 30 (the day before May 1st), trading ends at 1 pm, provided that day does not fall on a weekend.

As you said

One would want to specify that e.g. recurring days (as mentioned in this proposal) plus other specific (user specified) days should be excluded as business days.

This proposal does attempt to address the former part. The latter, however, varies hugely from region to region. For example, some places use one calendar for their business days, but observe holidays in another calendar. You can probably model it by combining two recurrence rules (in two calendars), or provide your own model to host user-specified holidays and filter them out manually while getting the recurrence of dates. But again that seems like a specific use case as that might not be how, say, Stockholm Exchange's trading hour works, so I'm not sure if that fits into this proposal's scope or even Foundation's.