rrules 0.2.0

A library for working with recurrence rules
Documentation
# RRules

A blazing fast and memory efficient library to manage recurrence rules inspired by the standards from [RFC-5547](https://icalendar.org/iCalendar-RFC-5545/3-3-10-recurrence-rule.html).
It provides the ability to define recurrence rules for events, and then iterate over them to get the dates that match the recurrence rules.

## How to use it

The easiest way to use this library is to start by loading a Recurrence instance from a string following the [standards](#standards):

### Loading from string

#### Required attributes:

- FREQ
  - Defines the type of frequency (E.g. DAILY, WEEKLY, MONTHLY, etc)
- INTERVAL
    - Defines the interval of the frequency (E.g. every 2 days, every 3 months, etc)
- DTSTART
    - Defines the start date of the recurrence

Examples:

```rust
// Daily recurrence example:

let recurrence = Recurrence::from_str("FREQ=DAILY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z"").unwrap();

```

> The `Recurrence` struct is an iterator that will yield all the dates that match the recurrence rules defined.

You can then use the `Recurrence` as an iterator by looping over it or collecting the results into a `Vec`

```rust
...
for event in recurrence {
    ...
}
# or
let events: Vec<DateTime<Utc>> = recurrence.collect();
```

### How to use it with structs definition

To define a recurrence rule, start by creating the desired `frequency` rule definition:

```rust
let daily = Frequency::Daily {
    interval: 1,
    by_time: vec![],
};
```

Then, create a `Recurrence` with the frequency defined:

```rust
...
let recurrence = Recurrence::new(
    daily,
    Utc::now(), // start date
    Some(Utc::now() + Duration::days(1)), // end date
    Some(Duration::hours(1)), // duration (optional
);
```

The `end` attribute of a `Recurrence` is optional, and if not specified, it will yield events until the `MAX_DATE`.
> The `MAX_DATE` is defined as `9999-12-31T23:59:59Z`

The `duration` attribute of a `Recurrence` is optional, and if not specified, it will use the default as 0 seconds `Duration::seconds(0)`.

<span id="standards"></span>
## Attribute standards

| Attribute  | Description                                                                                                    | Example                                                             |
|------------|----------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|
| FREQ       | Defines the type of frequency (E.g. DAILY, WEEKLY, MONTHLY, etc)                                               | FREQ=DAILY                                                          |
| INTERVAL   | Defines the interval of the frequency (E.g. every 2 days, every 3 months, etc)                                 | INTERVAL=2                                                          |
| DTSTART    | Defines the start date of the recurrence                                                                       | DTSTART=2023-01-01T12:00:00Z                                        |
| DTEND      | Defines the end date of the recurrence                                                                         | DTEND=2023-01-01T12:00:00Z                                          |
| DURATION   | Defines the duration of the recurrence                                                                         | DURATION=PT1H                                                       |
| BYDAY      | Defines the days of the week that the recurrence will happen                                                   | BYDAY=MO,TU -> When FREQ=WEEKLY; BYDAY=1MO,3WE -> When FREQ=MONTHLY |
| BYMONTHDAY | Defines the days of the month that the recurrence will happen                                                  | BYMONTHDAY=1,2,3,4, etc                                             |
| BYMONTH    | Defines the months of the year that the recurrence will happen                                                 | BYMONTH=1,2,3,4,5,6,7,8,9,10,11,12                                  |


## Supported recurrence rule types + examples
Current supporting recurrence rules:

- [Secondly]#secondly
- [minutely]#minutely
- [hourly]#hourly
- [Daily]#daily
- [Weekly]#weekly
- [Monthly]#monthly
    - [By month day]#monthly-by-month-day
    - [By nth weekday]#monthly-by-day
- [Yearly]#yearly
    - [By day]#yearly-by-day
    - [By month day]#yearly-by-month-day


<span id="secondly"></span>
### Secondly Frequencies
Represents the rules for a recurrence that happens every x seconds.

```rust
let every_second_recurrence = Recurrence::from_str(
    "FREQ=SECONDLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z"
).unwrap();
```

<span id="minutely"></span>
### Minutely Frequencies
Represents the rules for a recurrence that happens every x minutes.

```rust
let every_5_minutes = Recurrence::from_str(
    "FREQ=MINUTELY;INTERVAL=5;DTSTART=2023-01-01T12:00:00Z"
).unwrap();
```

<span id="hourly"></span>
### Hourly Frequencies
Represents the rules for a recurrence that happens every x hours.

```rust
let every_6_hours = Recurrence::from_str(
    "FREQ=HOURLY;INTERVAL=6;DTSTART=2023-01-01T12:00:00Z"
).unwrap();
```

<span id="daily"></span>
### Daily Frequencies
Represents the rules for a recurrence that happens x times every x days.

```rust

let every_3_days = Recurrence::from_str(
    "FREQ=DAILY;INTERVAL=3;DTSTART=2023-01-01T12:00:00Z"
).unwrap();

let every_day_at_8am = Recurrence::from_str(
    "FREQ=DAILY;INTERVAL=1;DTSTART=2023-01-01T08:00:00Z"
).unwrap();

let every_other_day_at_12pm_and_16pm = Recurrence::from_str(
    "FREQ=DAILY;INTERVAL=2;DTSTART=2023-01-01T00:00:00Z;BYTIME=12:00,16:00"
).unwrap();
```

<span id="weekly"></span>
### Weekly Frequencies
Represents the rules for a recurrence that happens x times every x weeks.

```rust
let every_week = Recurrence::from_str(
    "FREQ=WEEKLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z"
).unwrap();

let every_week_mon_and_tue = Recurrence::from_str(
    "FREQ=WEEKLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z;BYDAY=MO,TU"
).unwrap();
```
<span id="monthly"></span>
### Monthly Frequencies
Represents the rules for a recurrence that happens x times every x months.

```rust
let monthly = Recurrence::from_str(
    "FREQ=MONTHLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z"
).unwrap();
```

<span id="monthly-by-month-day"></span>
#### Monthly by month day

When specifying `BYMONTHDAY`, it will only yield the dates that match the days of the month specified.

```rust
let every_15th = Recurrence::from_str(
    "FREQ=MONTHLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z;BYMONTHDAY=15"
).unwrap();

let every_15th_and_30th = Recurrence::from_str(
    "FREQ=MONTHLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z;BYMONTHDAY=15,30"
).unwrap();
```

<span id="monthly-by-day"></span>
#### Monthly by nth day

When specifying `BYDAY`, it will only yield the dates that match the nth days of the week specified.
I.g. if you want to have a recurrence every first Monday of the month, you can do:

```rust
let every_first_monday = Recurrence::from_str(
    "FREQ=MONTHLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z;BYDAY=1MO"
).unwrap();

let every_first_monday_and_wednesday = Recurrence::from_str(
    "FREQ=MONTHLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z;BYDAY=1MO,1WE"
).unwrap();
```

<span id="yearly"></span>
### Yearly Frequencies
Represents the rules for a recurrence that happens x times every x years.

```rust
let yearly = Recurrence::from_str(
    "FREQ=YEARLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z"
).unwrap();
```

<span id="yearly-by-month-day"></span>
#### Yearly by month day
    
When specifying `BYMONTH` and `BYMONTHDAY`, it will only yield the dates that match the days of the month specified.
E.g. if you want to have a recurrence every 15th January of the year, you can do:
    
```rust
let every_15th_january = Recurrence::from_str(
    "FREQ=YEARLY;INTERVAL=1;DTSTART=2023-01-01T12:00:00Z;BYMONTH=1;BYMONTHDAY=15"
).unwrap();
```