#ical #calendar #rules #date #recurrence #rfc #recurrence-rules

bin+lib rrule

A pure Rust implementation of recurrence rules as defined in the iCalendar RFC

40 releases

0.13.0 Aug 3, 2024
0.12.0 Apr 4, 2024
0.11.0 Jul 18, 2023
0.10.0 Aug 8, 2022
0.3.4 Nov 13, 2020

#29 in Date and time

Download history 1508/week @ 2024-08-02 1724/week @ 2024-08-09 980/week @ 2024-08-16 1509/week @ 2024-08-23 2367/week @ 2024-08-30 2301/week @ 2024-09-06 1787/week @ 2024-09-13 1934/week @ 2024-09-20 2601/week @ 2024-09-27 1284/week @ 2024-10-04 1426/week @ 2024-10-11 1975/week @ 2024-10-18 1806/week @ 2024-10-25 1168/week @ 2024-11-01 1405/week @ 2024-11-08 1018/week @ 2024-11-15

5,793 downloads per month
Used in 7 crates (4 directly)

MIT/Apache

495KB
13K SLoC

RRule.rs

A pure and efficient Rust implementation of recurrence rules as defined in the iCalendar RFC.

Specification

This crate follows the iCalendar (RFC-5545) specification for the "Recurrence Rule". The Recurrence Rule spec corresponds to the RRule object in this crate. In addition, it allows for adding the "DTSTART" property separated by a newline.

The crate allows for a "BYEASTER" filter. But this is opt-in with the feature flag "by-easter".

RRuleSet

RRuleSet allows for a combination for RRules and some other properties.

  • List of RRules: Allows multiple RRules to be combined. (Union, A ∪ B)
  • List of RDates: A list of datetime combinations to always include. (Union, A ∪ B)
  • List of ExRule (see note below): Allows of RRules that are removed from the results. (Complement A \ B or A - B)
  • List of ExDate: A list of datetime combinations to always exclude. (Complement A \ B or A - B)

Note: "EXRULE" was originally part of RFC 2445, RFC 5545 obsoletes this specification. But "EXRULE" works exactly the same als "RRULE" except that it excludes dates. You can enable "EXRULE" by enabling the "exrule" feature flag which is disabled by default.

If you notice that the implementation differs from the specifications above, please open an issue.

Library Usage

use rrule::RRuleSet;

// RRule that starts 2012.02.01 and occurs daily for 3 days.
let rrule: RRuleSet = "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=3".parse().unwrap();

// Set hard limit in case of infinitely recurring rules.
let limit = 100;
// Get all recurrences of the rrule
let result = rrule.all(limit);
assert_eq!(result.dates.len(), 3);

See more examples at docs.rs

Command Line Tool Usage

Install the command line tool with:

cargo install rrule --features="cli-tool"

Then run it with:

rrule "DTSTART:20120201T093000Z\nRRULE:FREQ=DAILY;COUNT=3"

Security

You should read the security docs if you use arbitrary inputs from users for constructing the recurrence rules.

Limitation and limits

All dates are limited to the range or years +/-262_000[^1] because of Chrono limits. See Chrono's limits for more info.

Supported timezones are limited to by the timezones that Chrono-Tz supports. This is equivalent to the IANA database. See Chrono-Tz's limits for more info.

Validation Limits

Because the specifications do give a lot of flexibilities this can be abused very easily. In order to prevent most of the abuse we've imposed arbitrary limitation when on the RRuleSet::all method. The validation limits aren't enforced for the RRuleSet::all_unchecked method or when using the Iterator api directly.

Limitations:

Description Arbitrary Limit Crate Limit
Year range -10_000..=10_000 -262_000..=262_000 (Chrono)
Max interval with freq Yearly 10_000 (10000 years) 65_535 (u16::MAX)
Max interval with freq Monthly 1_000 (~83 years) 65_535 (u16::MAX)
Max interval with freq Weekly 1_000 (~19 years) 65_535 (u16::MAX)
Max interval with freq Daily 10_000 (~27 years) 65_535 (u16::MAX)
Max interval with freq Hourly 10_000 (~416 days) 65_535 (u16::MAX)
Max interval with freq Minutely 10_000 (~7 days) 65_535 (u16::MAX)
Max interval with freq Secondly 50_000 (~13 hours) 65_535 (u16::MAX)
Iteration limit 100_000 4_294_967_295 (u32::MAX)

By default, the "Arbitrary Limit" is used. If you instead want to use the "Crate Limit". Make sure you understand the risks that come with this.

Inspired by

License

The code in this project is licensed under the MIT or Apache 2.0 license.

All contributions to this project will be similarly licensed.

[^1]: See validation limits sections more info.

Dependencies

~4.5–7MB
~113K SLoC