Bodu.Globalization.Recurrence 1.0.0

dotnet add package Bodu.Globalization.Recurrence --version 1.0.0
                    
NuGet\Install-Package Bodu.Globalization.Recurrence -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bodu.Globalization.Recurrence" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bodu.Globalization.Recurrence" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Bodu.Globalization.Recurrence" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bodu.Globalization.Recurrence --version 1.0.0
                    
#r "nuget: Bodu.Globalization.Recurrence, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bodu.Globalization.Recurrence@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bodu.Globalization.Recurrence&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Bodu.Globalization.Recurrence&version=1.0.0
                    
Install as a Cake Tool

Bodu.Globalization.Recurrence

API stability — Stable. The public API surface is committed; breaking changes are reserved for a major-version bump per SemVer.

Recurrence-rule evaluation for .NET: four ways to express "when does this happen again?", each answering next- and previous-occurrence queries over DateTime and DateTimeOffset.

using Bodu.Globalization.Recurrence;

// RFC 5545 RRULE — the second Tuesday of every month
var rule = RecurrenceRule.Parse("FREQ=MONTHLY;BYDAY=2TU", null);
DateTime? next = rule.GetNextOccurrence(start: new DateTime(2026, 1, 1),
                                        after: new DateTime(2026, 3, 5),
                                        inclusive: false);

// Vixie cron — 06:30 on weekdays
var cron = CronExpression.Parse("30 6 * * 1-5");

// "every 4 hours after the last completed run"
var every4h = AnchoredInterval.Parse("PT4H", null);

Installation

dotnet add package Bodu.Globalization.Recurrence

Targets net8.0. Depends only on Bodu.Core — not on Bodu.Globalization.Calendar, which it is a sibling of rather than a layer on.

The four forms

Type Grammar For
RecurrenceRule RFC 5545 RRULE Calendar-style recurrence: FREQ/INTERVAL/COUNT/UNTIL/WKST and the full BY* model incl. BYSETPOS
RecurrenceSet iCalendar property block One or more rules composed with explicit RDATE additions and EXDATE exclusions
CronExpression Vixie cron Five-field, optional-seconds six-field, and the @yearly…@hourly macros
AnchoredInterval RFC 5545 §3.3.6 duration anchor + k·interval for k ≥ 1, with the anchor passed per query

RecurrenceRule implements IParsable/ISpanParsable/IFormattable and round-trips its canonical text. Every form carries a defect-naming TryParse(s, out result, out failureMessage) overload that says what was wrong rather than just returning false, and compares by value.

Purity

Every answer is a pure function of its arguments — no wall clock, no machine time zone. A query takes the instant to search from, so the same inputs always give the same answer, which makes schedules testable without freezing time. This is enforced, not merely intended: a metadata-scan guard (PurityTests) fails the build if a banned wall-clock or local-time-zone API appears anywhere in the assembly.

Correctness

Validated against an RFC 5545 §3.8.5.3 worked-example corpus, then hardened against defects reported to other implementations — python-dateutil, rrule.js, ical4j, ical.net, ical.js, libical, lib-recur, ice_cube, Cronos, NCrontab, cronie, croniter, robfig/cron and Quartz — with that corpus kept as regression tests. Fixes it produced include Vixie's leading-character rule for cron day-field restriction, candidate-set deduplication before BYSETPOS/COUNT, the BYDAY ordinal when BYDAY limits alongside BYMONTHDAY, and BYWEEKNO numbering generalized from the ISO rule to WKST.

Known limits

  • Sub-daily RRULE frequencies are not enumerated. HOURLY, MINUTELY and SECONDLY parse and round-trip, but GetNextOccurrence / GetPreviousOccurrence throw NotSupportedException naming the frequency. For sub-daily schedules use AnchoredInterval (or CronExpression, whose seconds-field layout covers the common cases).
  • Quartz cron extensions (L, W, #, ?) are rejected with NotSupportedException; the parser is Vixie-compatible.
  • CronExpression searches a documented 12-year horizon before reporting no occurrence.
  • No .ics reader — this package evaluates rules, it does not parse calendar files.

Part of the Bodu utility library.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 519 9/24/2026
0.7.0 137 9/24/2026
0.6.0 57 9/24/2026