Meziantou.Framework.Scheduling
4.1.0
Prefix Reserved
See the version list below for details.
dotnet add package Meziantou.Framework.Scheduling --version 4.1.0
NuGet\Install-Package Meziantou.Framework.Scheduling -Version 4.1.0
<PackageReference Include="Meziantou.Framework.Scheduling" Version="4.1.0" />
<PackageVersion Include="Meziantou.Framework.Scheduling" Version="4.1.0" />
<PackageReference Include="Meziantou.Framework.Scheduling" />
paket add Meziantou.Framework.Scheduling --version 4.1.0
#r "nuget: Meziantou.Framework.Scheduling, 4.1.0"
#:package Meziantou.Framework.Scheduling@4.1.0
#addin nuget:?package=Meziantou.Framework.Scheduling&version=4.1.0
#tool nuget:?package=Meziantou.Framework.Scheduling&version=4.1.0
Meziantou.Framework.Scheduling
This package supports 2 schedule formats:
- Recurrence rules (RRULE) as defined in RFC5545 and RFC2445
- Cron expressions
Recurrence rules (RRULE)
Parse recurrence rules:
var rrule = "FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1";
if (RecurrenceRule.TryParse(rrule, out var rule, out var error))
{
var nextOccurrences = rule.GetNextOccurrences(DateTime.Now).Take(50).ToArray();
}
Convert a recurrence rule to human-readable text:
var culture = CultureInfo.GetCultureInfo("en-US");
RecurrenceRule.Parse("FREQ=DAILY").GetHumanText(culture); // every day
RecurrenceRule.Parse("FREQ=WEEKLY;INTERVAL=3;BYDAY=TU;UNTIL=20150101").GetHumanText(culture); // every 3 weeks on Tuesday until January 1, 2015
Supported languages for human-readable text:
- English (
en,en-*, and invariant culture) - French (
fr,fr-*)
Time zones
GetNextOccurrences also accepts a time zone. The occurrences keep their wall-clock time across a daylight
saving transition, so each one carries the UTC offset in effect at that moment:
var rrule = RecurrenceRule.Parse("FREQ=DAILY;BYHOUR=9");
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
foreach (var occurrence in rrule.GetNextOccurrences(new DateTime(2024, 03, 09), timeZone).Take(3))
{
Console.WriteLine(occurrence);
}
// 2024-03-09 09:00:00 -05:00
// 2024-03-10 09:00:00 -04:00 <- the offset changes, the wall clock does not
// 2024-03-11 09:00:00 -04:00
The start date is read as a wall-clock time in that time zone, and a DateTimeOffset overload accepts an
instant instead. A time zone identifier can be passed directly, which TimeZones.Find resolves:
var occurrences = rrule.GetNextOccurrences(startDate, "America/New_York");
A local time that a transition makes invalid or ambiguous is resolved as RFC 5545 section 3.3.5 requires:
an ambiguous time keeps its first occurrence, and an invalid time is read with the UTC offset in effect
before the gap, so 02:30 on a spring-forward day surfaces as 03:30 at the new offset. This is what
errata 4271 settles for recurrence instances; only an invalid
date, such as February 30, is dropped from the recurrence set.
Reading a gap that way maps it onto the instants of the hour that follows it, so a sub-hourly recurrence
would otherwise repeat them. Those duplicates are ignored, per RFC 5545 section 3.8.5.3, and do not count
towards COUNT. Across a backward transition the repeated hour is visited once, so its second pass is not
produced.
UNTIL is honoured as an instant when it is a UTC value, and as a wall-clock reading when it is floating.
CronExpression supports the same overloads.
iCalendar
InternetCalendar writes events in the iCalendar format. Setting Event.TimeZone writes the start and end
as DTSTART;TZID=/DTEND;TZID= and emits a matching VTIMEZONE component:
var calendar = new InternetCalendar();
calendar.Events.Add(new Event
{
Start = new DateTime(2024, 01, 02, 08, 00, 00),
End = new DateTime(2024, 01, 02, 09, 00, 00),
TimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/New_York"),
});
var ics = calendar.ToIcs();
BEGIN:VTIMEZONE
TZID:America/New_York
BEGIN:DAYLIGHT
DTSTART:20070311T020000
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
...
DTSTART;TZID=America/New_York:20240102T080000
A Start or End whose Kind is Unspecified is taken as a wall-clock reading in that time zone; a Utc
or Local value denotes an instant and is converted to it. The component describes the adjustment rule in
effect for the events, expanded to an open-ended yearly recurrence.
Cron expressions
The library also provides CronExpression to parse and evaluate cron schedules.
var cron = CronExpression.Parse("0 */15 * * * *");
var occurrences = cron.GetNextOccurrences(DateTime.Now).Take(10).ToArray();
Supported formats
- 5 fields:
minute hour day-of-month month day-of-week - 6 fields:
second minute hour day-of-month month day-of-week - 7 fields:
second minute hour day-of-month month day-of-week year
When using the 5-field format, seconds are implicitly set to 0.
Field ranges
- second:
0-59 - minute:
0-59 - hour:
0-23 - day-of-month:
1-31 - month:
1-12orJAN-DEC - day-of-week:
0-6orSUN-SAT(0= Sunday) - year (optional):
1970-2099
Operators and special values
For all fields:
*or?: any valuea,b,c: lista-b: range*/n: step from field minimuma-b/n: stepped rangea/n: step starting ata
Day-of-month field additionally supports:
L: last day of monthL-n: nth day before end of month (for exampleL-2)LW: last weekday of monthnW: nearest weekday to dayn
Day-of-week field additionally supports:
nL: last occurrence of weekdaynin monthn#m: m-th occurrence of weekdaynin month (min1-5)
Predefined schedules
@yearly/@annually@monthly@weekly@daily/@midnight@hourly
Notes
- Parsing is case-insensitive for month/day names and predefined schedules.
day-of-monthandday-of-weekare combined with AND semantics. A date must satisfy both fields to match.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. net11.0 is compatible. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Memory (>= 4.6.3)
-
net10.0
- No dependencies.
-
net11.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Meziantou.Framework.Scheduling:
| Package | Downloads |
|---|---|
|
Immediate.Jobs
A reflection-free background job scheduler for .NET using source generation. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.1.3 | 842 | 9/20/2026 |
| 4.1.2 | 236 | 9/15/2026 |
| 4.1.1 | 411 | 9/6/2026 |
| 4.1.0 | 127 | 9/4/2026 |
| 4.0.5 | 124 | 9/3/2026 |
| 4.0.4 | 102 | 9/3/2026 |
| 4.0.3 | 155 | 8/30/2026 |
| 4.0.2 | 264 | 8/16/2026 |
| 4.0.1 | 601 | 7/8/2026 |
| 4.0.0 | 170 | 7/5/2026 |
| 3.0.2 | 308 | 6/13/2026 |
| 3.0.1 | 301 | 5/23/2026 |
| 3.0.0 | 163 | 5/17/2026 |
| 2.0.12 | 198 | 5/11/2026 |
| 2.0.11 | 371 | 3/22/2026 |
| 2.0.10 | 443 | 1/16/2026 |
| 2.0.9 | 389 | 11/2/2025 |
| 2.0.8 | 200 | 10/19/2025 |
| 2.0.7 | 290 | 9/3/2025 |
| 2.0.6 | 322 | 3/1/2025 |