recurring 0.1.2

A vector-based map and set implementation
Documentation

recurring

Build Status crates.io docs.rs License: Apache 2.0 License: MIT

An event series implementation based on jiff which provides a flexible alternative to jiff's builtin series iterators provided by the DateTime::series, Date::series and Time::series methods.

The essential types in this crate are:

  • Pattern: a trait implemented by recurrence patterns to yield a DateTime before, after or close to a given instant.
  • Event: an event with a start and optional end date.
  • Series: produces Events following a recurrence Pattern.

Features

Example: Series with cron pattern

use recurring::{Event, Series};
use recurring::pattern::cron;
use jiff::civil::date;

let start = date(2025, 7, 1).at(12, 0, 0, 0);
let pattern = cron().hours([12, 16]).minute(5).seconds([10, 20]);
let series = Series::new(start.., pattern);

let events: Vec<Event> = series.iter().take(5).collect();

assert_eq!(
    events,
    [
        Event::at(date(2025, 7, 1).at(12, 5, 10, 0)),
        Event::at(date(2025, 7, 1).at(12, 5, 20, 0)),
        Event::at(date(2025, 7, 1).at(16, 5, 10, 0)),
        Event::at(date(2025, 7, 1).at(16, 5, 20, 0)),
        Event::at(date(2025, 7, 2).at(12, 5, 10, 0)),
    ]
);

Example: Series with interval pattern from a jiff type

use recurring::{Event, Series, ToSeries};
use recurring::pattern::daily;
use jiff::civil::date;

let start = date(2025, 7, 1).at(12, 0, 0, 0);
let series = start.to_series(daily(2)).unwrap();

let events: Vec<Event> = series.iter().take(5).collect();

assert_eq!(
    events,
    [
        Event::at(date(2025, 7, 1).at(12, 0, 0, 0)),
        Event::at(date(2025, 7, 3).at(12, 0, 0, 0)),
        Event::at(date(2025, 7, 5).at(12, 0, 0, 0)),
        Event::at(date(2025, 7, 7).at(12, 0, 0, 0)),
        Event::at(date(2025, 7, 9).at(12, 0, 0, 0)),
    ]
);

Example: Series with event duration and multiple recurrence patterns

use recurring::{Combine, Event, Series};
use recurring::pattern::cron;
use jiff::{civil::date, ToSpan};

let start = date(2025, 6, 30).at(0, 0, 0, 0);
let daily_around_lunch = cron().hour(12).minute(5).second(10);
let first_of_month_in_the_morning = cron().day(1).hour(8).minute(45).second(0);
let pattern = daily_around_lunch.and(first_of_month_in_the_morning);

let series = Series::new(start.., pattern)
    .with()
    .event_duration(1.hour())
    .build()
    .unwrap();

let events: Vec<Event> = series.iter().take(4).collect();

assert_eq!(
    events,
    [
        Event::new(
            date(2025, 6, 30).at(12, 5, 10, 0),
            date(2025, 6, 30).at(13, 5, 10, 0),
        ),
        Event::new(
            date(2025, 7, 1).at(8, 45, 0, 0),
            date(2025, 7, 1).at(9, 45, 0, 0),
        ),
        Event::new(
            date(2025, 7, 1).at(12, 5, 10, 0),
            date(2025, 7, 1).at(13, 5, 10, 0),
        ),
        Event::new(
            date(2025, 7, 2).at(12, 5, 10, 0),
            date(2025, 7, 2).at(13, 5, 10, 0),
        ),
    ]
);

Example: Querying a Series for events before, after or close to a datetime

use recurring::{Combine, Event, Series};
use recurring::pattern::cron;
use jiff::{civil::date, ToSpan};

let start = date(2025, 7, 1).at(0, 0, 0, 0);
let end = date(2025, 7, 10).at(0, 0, 0, 0);
let pattern = cron().hours([12, 18]).minutes([5, 10]).second(0);

let series = Series::new(start..end, pattern);

assert_eq!(
    series.get_next_after(start),
    Some(Event::at(date(2025, 7, 1).at(12, 5, 0, 0))),
);

assert_eq!(
    series.get_previous_before(end),
    Some(Event::at(date(2025, 7, 9).at(18, 10, 0, 0))),
);

assert_eq!(
    series.get_closest_to(date(2025, 7, 5).at(0, 0, 0, 0)),
    Some(Event::at(date(2025, 7, 4).at(18, 10, 0, 0))),
);

License

The source code of recurring is licensed under either of Apache License, Version 2.0 or MIT license at your option.