Crates.io | calends |
lib.rs | calends |
version | 0.2.0-alpha.8 |
source | src |
created_at | 2022-08-06 17:10:37.915455 |
updated_at | 2023-01-09 01:55:18.844052 |
description | Calendar library for Rust |
homepage | |
repository | |
max_upload_size | |
id | 639928 |
size | 100,370 |
calends is a library for durations, intervals and other calendar related operations. It is designed to work with chrono.
Calends was built to extend the current date time tools that exist in the ecosystem such as chrono. Its main focus is on finding and handling more complex things such as intervals of time, durations which focus on months or longer (chrono does not support months), complicated recurrence rules such as "the 3rd day of the month recurring 3 times".
In addition to supporting the date time logic it is also important to consider ISO8601-2:2019. This standard was created to extend the current ISO8601 standard and add support for intervals, durations, recurring times. This is not a widely adopted standard (likely due to its closed and very expensive nature).
Many concepts that are in this library have been influenced by the ISO8601-2:2019 standard and CalConnect.
A RelativeDuration is a unit of time that has some ability to be applied to a date to produce another date.
use calends::RelativeDuration;
use chrono::NaiveDate;
// This will allow you to add one month and then go back two days from the added month
let rd = RelativeDuration::months(1).with_days(-2);
// It also compatible with NaiveDate
assert_eq!(
NaiveDate::from_ymd(2022, 1, 1) + rd,
NaiveDate::from_ymd(2022, 1, 30)
);
When applying durations to dates, it will apply in order if the largest units first e.g. months will come before weeks. Therefore when you construct durations such as 1 month, -1 day it will then move forward 1 month and then go backwards one day.
There are two ways to serialize a RelativeDuration:
use calends::RelativeDuration;
use calends::rd_iso8601;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct S {
#[serde(
deserialize_with = "rd_iso8601::deserialize",
serialize_with = "rd_iso8601::serialize"
)]
rd: RelativeDuration,
}
let rd = RelativeDuration::default().with_days(1).with_months(23).with_weeks(-1);
let s = S { rd };
let rd_string = serde_json::to_string(&s).unwrap();
assert_eq!(rd_string, r#"{"rd":"P23M-1W1D"}"#);
let parsed: S = serde_json::from_str(&rd_string).unwrap();
assert_eq!(rd, parsed.rd)
[Recurrence] allows you to specify a ruleset for how events (dates) repeat in time.
use calends::{Recurrence, Rule};
use chrono::NaiveDate;
let date = NaiveDate::from_ymd(2022, 1, 1);
let end = NaiveDate::from_ymd(2022, 3, 1);
let mut recur = Recurrence::with_start(Rule::monthly(), date).until(end);
assert_eq!(recur.next(), Some(NaiveDate::from_ymd(2022, 1, 1)));
assert_eq!(recur.next(), Some(NaiveDate::from_ymd(2022, 2, 1)));
assert_eq!(recur.next(), None);
An interval is a span of time that can be bound or unbound. There are three important cases to consider: closed, unbounded start, and unbounded end.
In combination with RelativeDuration you can do things such as iterate the second to last day of the month.
use calends::{Interval, RelativeDuration};
use chrono::NaiveDate;
let duration = RelativeDuration::months(1).with_days(-2);
let start = NaiveDate::from_ymd(2022, 1, 1);
let mut interval = Interval::closed_from_start(start, duration);
There are two ways to serialize a Interval:
use chrono::NaiveDate;
use calends::{Interval, RelativeDuration, IntervalLike};
use calends::interval::marker::Start;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct S {
i: Interval,
}
let rd = RelativeDuration::default().with_days(1).with_months(23).with_weeks(-1);
let int = Interval::closed_from_start(NaiveDate::from_ymd(2022, 1, 1), rd);
let s = S { i: int.clone() };
let int_string = serde_json::to_string(&s).unwrap();
assert_eq!(int_string, r#"{"i":"2022-01-01/2023-11-25"}"#);
let parsed: S = serde_json::from_str(&int_string).unwrap();
assert_eq!(parsed.i.start_opt().unwrap(), int.start_opt().unwrap())
License: MIT