Table of Contents

RecurrenceRule Class

Definition

Namespace
Bodu.Globalization.Recurrence
Assembly
Bodu.Globalization.Recurrence.dll
Package
Bodu.Globalization.Recurrence 1.0.0
Source
RecurrenceRule.Formatting.cs

Represents an immutable RFC 5545 recurrence rule (RRULE): a base Frequency refined by an interval, an optional bound (Count or Until), and the BY rule parts, from which the set of recurring instants relative to a start date is derived.

public sealed class RecurrenceRule : IEquatable<RecurrenceRule>, IFormattable, ISpanParsable<RecurrenceRule>, IParsable<RecurrenceRule>
Inheritance
RecurrenceRule
Implements
Inherited Members
Extension Methods

Remarks

A rule is constructed by parsing its textual form with Parse(string) or fluently with RecurrenceRuleBuilder, and is expanded into concrete occurrences by the GetOccurrences and GetNextOccurrence methods, which take the series start date as their anchor. The rule itself carries no start date; the same rule can be applied to different starts.

Occurrence enumeration currently supports the Daily, Weekly, Monthly, and Yearly frequencies. A rule with a sub-daily frequency still parses and round-trips, but enumerating it throws NotSupportedException until that follow-on lands.

Every occurrence answer is a pure function of the arguments: no API reads the wall clock or consults the machine time zone. The DateTimeOffset overloads expand the rule on the wall-clock time of the series start and return occurrences carrying the start's offset; daylight-saving transitions are the caller's concern - a host that wants a local-time schedule across a transition re-derives the offset on each evaluation.

Properties

ByDay

Gets the weekday entries selected by the BYDAY rule part.

public IReadOnlyList<WeekDayNum> ByDay { get; }

Property Value

IReadOnlyList<WeekDayNum>

The selected weekday entries in source order, or an empty list when the rule part is absent.

ByHour

Gets the hours selected by the BYHOUR rule part.

public IReadOnlyList<int> ByHour { get; }

Property Value

IReadOnlyList<int>

The selected hours in source order, or an empty list when the rule part is absent.

ByMinute

Gets the minutes selected by the BYMINUTE rule part.

public IReadOnlyList<int> ByMinute { get; }

Property Value

IReadOnlyList<int>

The selected minutes in source order, or an empty list when the rule part is absent.

ByMonth

Gets the months selected by the BYMONTH rule part.

public IReadOnlyList<int> ByMonth { get; }

Property Value

IReadOnlyList<int>

The selected months in source order, or an empty list when the rule part is absent.

ByMonthDay

Gets the month days selected by the BYMONTHDAY rule part.

public IReadOnlyList<int> ByMonthDay { get; }

Property Value

IReadOnlyList<int>

The selected month days in source order, or an empty list when the rule part is absent.

BySecond

Gets the seconds selected by the BYSECOND rule part.

public IReadOnlyList<int> BySecond { get; }

Property Value

IReadOnlyList<int>

The selected seconds in source order, or an empty list when the rule part is absent.

BySetPos

Gets the set positions selected by the BYSETPOS rule part.

public IReadOnlyList<int> BySetPos { get; }

Property Value

IReadOnlyList<int>

The selected set positions in source order, or an empty list when the rule part is absent.

ByWeekNo

Gets the week numbers selected by the BYWEEKNO rule part.

public IReadOnlyList<int> ByWeekNo { get; }

Property Value

IReadOnlyList<int>

The selected week numbers in source order, or an empty list when the rule part is absent.

ByYearDay

Gets the year days selected by the BYYEARDAY rule part.

public IReadOnlyList<int> ByYearDay { get; }

Property Value

IReadOnlyList<int>

The selected year days in source order, or an empty list when the rule part is absent.

Count

Gets the maximum number of occurrences the rule produces.

public int? Count { get; }

Property Value

int?

The occurrence count from the COUNT rule part, or null when unbounded by count.

Frequency

Gets the base period at which the rule repeats.

public RecurrenceFrequency Frequency { get; }

Property Value

RecurrenceFrequency

The recurrence frequency, corresponding to the FREQ rule part.

Interval

Gets the positive multiple of Frequency between successive occurrences.

public int Interval { get; }

Property Value

int

The recurrence interval; 1 when the INTERVAL rule part is absent.

Until

Gets the inclusive upper bound beyond which no occurrence is produced.

public DateTime? Until { get; }

Property Value

DateTime?

The instant from the UNTIL rule part, or null when unbounded by date.

WeekStart

Gets the day on which the week starts for weekly-interval and week-number calculations.

public DayOfWeek WeekStart { get; }

Property Value

DayOfWeek

The week-start day from the WKST rule part; Monday when absent.

Methods

Equals(RecurrenceRule?)

Determines whether this rule is equal to another rule by comparing every component.

public bool Equals(RecurrenceRule? other)

Parameters

other RecurrenceRule

The rule to compare with this instance.

Returns

bool

true when other is non-null and every rule component is equal; otherwise false.

Equals(object?)

Determines whether this rule is equal to another object.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare with this instance.

Returns

bool

true when obj is a RecurrenceRule equal to this instance; otherwise false.

GetHashCode()

Returns a hash code derived from the rule's scalar components.

public override int GetHashCode()

Returns

int

A hash code for the current rule.

Remarks

The hash combines the scalar components (Frequency, Interval, Count, Until, WeekStart) and the rule-part lengths, which is a valid hash consistent with Equals(RecurrenceRule?) while avoiding per-element enumeration.

GetNextOccurrence(DateTime, DateTime, bool)

Returns the first occurrence of the rule that falls after the specified instant.

public DateTime? GetNextOccurrence(DateTime start, DateTime after, bool inclusive = false)

Parameters

start DateTime

The series start (DTSTART) the rule is anchored to.

after DateTime

The instant the returned occurrence must follow.

inclusive bool

true to allow an occurrence exactly equal to after; otherwise the occurrence must be strictly later.

Returns

DateTime?

The next occurrence, or null when the rule produces none.

Remarks

The search is bounded by the end of the representable calendar (year 9999): a rule that can never match, such as 30 February yearly, answers null rather than scanning unboundedly.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetNextOccurrence(DateTimeOffset, DateTimeOffset, bool)

Returns the first occurrence of the rule that falls after the specified instant, preserving the start's offset.

public DateTimeOffset? GetNextOccurrence(DateTimeOffset start, DateTimeOffset after, bool inclusive = false)

Parameters

start DateTimeOffset

The series start (DTSTART) the rule is anchored to.

after DateTimeOffset

The instant the returned occurrence must follow.

inclusive bool

true to allow an occurrence exactly equal to after; otherwise the occurrence must be strictly later.

Returns

DateTimeOffset?

The next occurrence, or null when the rule produces none.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetOccurrences(DateTime)

Enumerates the occurrences of the rule anchored at the specified start instant.

public IEnumerable<DateTime> GetOccurrences(DateTime start)

Parameters

start DateTime

The series start (DTSTART) the rule is anchored to.

Returns

IEnumerable<DateTime>

The occurrences in ascending chronological order, each preserving the Kind of start. The sequence is bounded when the rule declares Count or Until, and otherwise continues to the end of the representable calendar; use Take<TSource>(IEnumerable<TSource>, int) or the windowed overload to bound it.

Remarks

Whether an instant is an occurrence depends only on the rule and start, never on any query window, so the windowed overload and this method agree on membership. The start instant is itself emitted only when it satisfies the rule.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetOccurrences(DateTime, DateTime, DateTime)

Enumerates the occurrences of the rule that fall within an inclusive window.

public IEnumerable<DateTime> GetOccurrences(DateTime start, DateTime from, DateTime to)

Parameters

start DateTime

The series start (DTSTART) the rule is anchored to.

from DateTime

The inclusive lower bound of the window.

to DateTime

The inclusive upper bound of the window.

Returns

IEnumerable<DateTime>

The occurrences within [from, to] in ascending chronological order.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetOccurrences(DateTimeOffset)

Enumerates the occurrences of the rule anchored at the specified start, preserving its UTC offset.

public IEnumerable<DateTimeOffset> GetOccurrences(DateTimeOffset start)

Parameters

start DateTimeOffset

The series start (DTSTART) the rule is anchored to.

Returns

IEnumerable<DateTimeOffset>

The occurrences in ascending chronological order, each carrying the offset of start.

Remarks

Expansion is performed on the wall-clock time of start and the fixed offset is reattached to each result; daylight-saving transitions are not modeled (the rule carries no time zone).

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetOccurrences(DateTimeOffset, DateTimeOffset, DateTimeOffset)

Enumerates the occurrences of the rule that fall within an inclusive window, preserving the start's offset.

public IEnumerable<DateTimeOffset> GetOccurrences(DateTimeOffset start, DateTimeOffset from, DateTimeOffset to)

Parameters

start DateTimeOffset

The series start (DTSTART) the rule is anchored to.

from DateTimeOffset

The inclusive lower bound of the window.

to DateTimeOffset

The inclusive upper bound of the window.

Returns

IEnumerable<DateTimeOffset>

The occurrences within [from, to] in ascending chronological order.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetPreviousOccurrence(DateTime, DateTime, bool)

Returns the last occurrence of the rule that falls before the specified instant.

public DateTime? GetPreviousOccurrence(DateTime start, DateTime before, bool inclusive = false)

Parameters

start DateTime

The series start (DTSTART) the rule is anchored to.

before DateTime

The instant the returned occurrence must precede.

inclusive bool

true to allow an occurrence exactly equal to before; otherwise the occurrence must be strictly earlier.

Returns

DateTime?

The previous occurrence, or null when none precedes before.

Remarks

Due-ness evaluation is a previous-occurrence comparison - typically lastCompleted < GetPreviousOccurrence(now, inclusive: true) - so missed occurrences coalesce structurally: the answer is a single instant, never a backlog.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

GetPreviousOccurrence(DateTimeOffset, DateTimeOffset, bool)

Returns the last occurrence of the rule that falls before the specified instant, preserving the start's offset.

public DateTimeOffset? GetPreviousOccurrence(DateTimeOffset start, DateTimeOffset before, bool inclusive = false)

Parameters

start DateTimeOffset

The series start (DTSTART) the rule is anchored to.

before DateTimeOffset

The instant the returned occurrence must precede.

inclusive bool

true to allow an occurrence exactly equal to before; otherwise the occurrence must be strictly earlier.

Returns

DateTimeOffset?

The previous occurrence, or null when none precedes before.

Exceptions

NotSupportedException

Thrown when the rule uses a sub-daily frequency.

Parse(string)

Parses the textual form of a recurrence rule, such as FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR.

public static RecurrenceRule Parse(string s)

Parameters

s string

The rule text to parse. An optional leading RRULE: prefix is accepted.

Returns

RecurrenceRule

The parsed rule.

Exceptions

ArgumentNullException

Thrown when s is null.

FormatException

Thrown when s is not a valid recurrence rule.

ToString()

Returns the canonical RFC 5545 text of the rule, such as FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR.

public override string ToString()

Returns

string

The canonical rule text, which round-trips through Parse(string).

ToString(string?)

Returns the canonical RFC 5545 text of the rule.

public string ToString(string? format)

Parameters

format string

The format specifier. Only the general specifier ("G" or null) is supported.

Returns

string

The canonical rule text.

Exceptions

FormatException

Thrown when format is not a supported specifier.

ToString(string?, IFormatProvider?)

Returns the canonical RFC 5545 text of the rule.

public string ToString(string? format, IFormatProvider? formatProvider)

Parameters

format string

The format specifier. Only the general specifier ("G" or null) is supported.

formatProvider IFormatProvider

Unused; recurrence-rule text is culture-invariant.

Returns

string

The canonical rule text.

Exceptions

FormatException

Thrown when format is not a supported specifier.

TryParse(string?, out RecurrenceRule)

Attempts to parse the textual form of a recurrence rule.

public static bool TryParse(string? s, out RecurrenceRule result)

Parameters

s string

The rule text to parse.

result RecurrenceRule

The parsed rule, or null on failure.

Returns

bool

true if parsing succeeded; otherwise false.

TryParse(string?, out RecurrenceRule, out string?)

Attempts to parse the textual form of a recurrence rule, reporting the parse defect on failure.

public static bool TryParse(string? s, out RecurrenceRule result, out string? failureMessage)

Parameters

s string

The rule text to parse.

result RecurrenceRule

The parsed rule, or null on failure.

failureMessage string

null on success; otherwise a message naming the specific defect, suitable for surfacing to the user verbatim.

Returns

bool

true if parsing succeeded; otherwise false.

Explicit Interface Implementations

Parse(ReadOnlySpan<char>, IFormatProvider?)

Parses the textual form of a recurrence rule from a character span.

static RecurrenceRule Parse(ReadOnlySpan<char> s, IFormatProvider? provider)

Parameters

s ReadOnlySpan<char>

The rule text to parse. An optional leading RRULE: prefix is accepted.

provider IFormatProvider

Unused; recurrence-rule text is culture-invariant.

Returns

RecurrenceRule

The parsed rule.

Exceptions

FormatException

Thrown when s is not a valid recurrence rule.

Parse(string, IFormatProvider?)

Parses the textual form of a recurrence rule.

static RecurrenceRule Parse(string s, IFormatProvider? provider)

Parameters

s string

The rule text to parse. An optional leading RRULE: prefix is accepted.

provider IFormatProvider

Unused; recurrence-rule text is culture-invariant.

Returns

RecurrenceRule

The parsed rule.

Exceptions

ArgumentNullException

Thrown when s is null.

FormatException

Thrown when s is not a valid recurrence rule.

TryParse(ReadOnlySpan<char>, IFormatProvider?, out RecurrenceRule)

Attempts to parse the textual form of a recurrence rule from a character span.

static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out RecurrenceRule result)

Parameters

s ReadOnlySpan<char>

The rule text to parse.

provider IFormatProvider

Unused; recurrence-rule text is culture-invariant.

result RecurrenceRule

The parsed rule, or null on failure.

Returns

bool

true if parsing succeeded; otherwise false.

TryParse(string?, IFormatProvider?, out RecurrenceRule)

Attempts to parse the textual form of a recurrence rule.

static bool TryParse(string? s, IFormatProvider? provider, out RecurrenceRule result)

Parameters

s string

The rule text to parse.

provider IFormatProvider

Unused; recurrence-rule text is culture-invariant.

result RecurrenceRule

The parsed rule, or null on failure.

Returns

bool

true if parsing succeeded; otherwise false.

Applies to

ProductVersions
.NET8, 10

See Also