#events #recurring #date #repeat

recurring_event

Calculate dates for recurring events (daily, weekly, monthly and yearly)

4 releases

0.1.3 Aug 30, 2022
0.1.2 Aug 29, 2022
0.1.1 Aug 29, 2022
0.1.0 Aug 29, 2022

#368 in Date and time

21 downloads per month

MIT license

125KB
860 lines

Overview

This crate provides a set of components that describe the properties and behaviors of recurring events.

The typical usage of this crate is to create a recurring event, define its recurrences rules (e.g. happens on every tuesday, happens on the 15th of the month) and then get from the event the next date(s) that match the rules.

Four periodicities are currently supported (daily, weekly, monthly and yearly) through four types : DailyEvent, WeeklyEvent, MonthlyEvent and YearlyEvent.

Example of using a yearly event

use recurring_event::{YearlyEvent, Ordinal, Recurrent, MonthlyWeekdayOrdinal,
    time::{Month, OffsetDateTime, Weekday, macros::datetime}};

// This yearly event starts recurring on the 14th of November 2018.
let mut event = YearlyEvent::new(datetime!(2018-11-14 00:00 UTC));

// It's an event that recurs every four years.
event.update_frequency(4);

// On a year, the event happens on every Monday and Thursday of February.
event.insert_weekday(Weekday::Monday, Month::February);
event.insert_weekday(Weekday::Thursday, Month::February);

// And also on the 7th and 15th of February.
event.insert_monthly_day_ordinal(7, Month::February);
event.insert_monthly_day_ordinal(25, Month::February);

// And also on the second Tuesday and the last Sunday of February.
event.insert_monthly_weekday_ordinal(
    MonthlyWeekdayOrdinal::new(Ordinal::Second, Weekday::Tuesday),
    Month::February);
event.insert_monthly_weekday_ordinal(
    MonthlyWeekdayOrdinal::new(Ordinal::Last, Weekday::Sunday),
    Month::February);

// The event also happens on August, every Tuesday and Saturday.
event.insert_weekday(Weekday::Tuesday, Month::August);
event.insert_weekday(Weekday::Saturday, Month::August);

// And on the 13th and 29th of August.
event.insert_monthly_day_ordinal(13, Month::August);
event.insert_monthly_day_ordinal(29, Month::August);

// And on the first Wednesday and third Friday of August.
event.insert_monthly_weekday_ordinal(
    MonthlyWeekdayOrdinal::new(Ordinal::First, Weekday::Wednesday),
    Month::August);
event.insert_monthly_weekday_ordinal(
    MonthlyWeekdayOrdinal::new(Ordinal::Third, Weekday::Friday),
    Month::August);

// One possibility for getting the next occurrence dates is to take
// advantage of the fact that a YearlyEvent implement the Iterator trait.
// Let's get the next fourty occurrence dates !
let next_occurrences_dates: Vec<OffsetDateTime> = event.take(40).collect();

let expected_dates = vec![datetime!(2022-02-03 00:00 UTC),
    datetime!(2022-02-07 00:00 UTC),
    datetime!(2022-02-08 00:00 UTC),
    datetime!(2022-02-10 00:00 UTC),
    datetime!(2022-02-14 00:00 UTC),
    datetime!(2022-02-17 00:00 UTC),
    datetime!(2022-02-21 00:00 UTC),
    datetime!(2022-02-24 00:00 UTC),
    datetime!(2022-02-25 00:00 UTC),
    datetime!(2022-02-27 00:00 UTC),
    datetime!(2022-02-28 00:00 UTC),
    datetime!(2022-08-02 00:00 UTC),
    datetime!(2022-08-03 00:00 UTC),
    datetime!(2022-08-06 00:00 UTC),
    datetime!(2022-08-09 00:00 UTC),
    datetime!(2022-08-13 00:00 UTC),
    datetime!(2022-08-16 00:00 UTC),
    datetime!(2022-08-19 00:00 UTC),
    datetime!(2022-08-20 00:00 UTC),
    datetime!(2022-08-23 00:00 UTC),
    datetime!(2022-08-27 00:00 UTC),
    datetime!(2022-08-29 00:00 UTC),
    datetime!(2022-08-30 00:00 UTC),
    datetime!(2026-02-02 00:00 UTC),
    datetime!(2026-02-05 00:00 UTC),
    datetime!(2026-02-07 00:00 UTC),
    datetime!(2026-02-09 00:00 UTC),
    datetime!(2026-02-10 00:00 UTC),
    datetime!(2026-02-12 00:00 UTC),
    datetime!(2026-02-16 00:00 UTC),
    datetime!(2026-02-19 00:00 UTC),
    datetime!(2026-02-22 00:00 UTC),
    datetime!(2026-02-23 00:00 UTC),
    datetime!(2026-02-25 00:00 UTC),
    datetime!(2026-02-26 00:00 UTC),
    datetime!(2026-08-01 00:00 UTC),
    datetime!(2026-08-04 00:00 UTC),
    datetime!(2026-08-05 00:00 UTC),
    datetime!(2026-08-08 00:00 UTC),
    datetime!(2026-08-11 00:00 UTC)];

assert_eq!(expected_dates, next_occurrences_dates)

time crate

This crate uses the time crate, in particular the OffsetDateTime, Month, and Weekday types.

An OffsetDateTime stores time and offset (i.e. timezone) information. Currently, this crate doesn't make any use of them. It is available for your code, should you need to manage specific time and offset in your event.

serde and typetag crates

(De)serialization of event types is available thanks to serde, and (de)serialization of Box<dyn Recurrent> trait object thanks to typetag.

Dependencies

~1.7–2.7MB
~55K SLoC