### Example: using with_rolling_day on a monthly DateRule Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html Shows how to create a monthly DateRule starting from February 29, 2020, and apply with_rolling_day(31) to ensure dates fall on the 31st (or shifted backwards for month ends). The example asserts the first four yielded dates. ```rust let start = NaiveDate::from_ymd_opt(2020, 2, 29).unwrap(); let mut rule = DateRule::monthly(start).with_rolling_day(31).unwrap(); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 4, 30).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 5, 31).unwrap()); // etc. ``` -------------------------------- ### Chronoutil Crate Documentation and Examples Source: https://docs.rs/chronoutil/latest/src/chronoutil/lib.rs.html?search=u32+-%3E+bool This is the crate-level documentation for chronoutil, which includes code examples demonstrating the RelativeDuration API, edge cases, DateRule usage, and the non-associative nature of adding months. ```rust #![warn(missing_docs)] //! # Chronoutil provides powerful extensions to rust's Chrono crate //! //! ChronoUtil provides the following utilities: //! - `RelativeDuration`: extending Chrono's `Duration` to add months and years //! - `DateRule`: useful iterators yielding regular (e.g. monthly) dates //! - Procedural helper functions for shifting datelike values by months and years //! //! It is heavily inspired by Python's [dateutil](https://github.com/dateutil/dateutil) //! and provides a similar API, but with less of the niche functionality. //! ## Overview //! //! ### RelativeDuration //! //! ChronoUtils uses a [RelativeDuration] type to represent the magnitude of a time span //! which may not be absolute (i.e. which is not simply a fixed number of nanoseconds). //! A relative duration is made up of a number of months together with an absolute duration //! component. //! //! ```rust //! # use chrono::{NaiveDate}; //! # use chronoutil::{RelativeDuration}; //! let one_day = RelativeDuration::days(1); //! let one_month = RelativeDuration::months(1); //! let delta = one_month + one_day; //! let start = NaiveDate::from_ymd_opt(2020, 1, 1).unwrap(); //! assert_eq!(start + delta, NaiveDate::from_ymd_opt(2020, 2, 2).unwrap()); //! ``` //! //! The behaviour of `RelativeDuration` is consistent and well-defined in edge-cases //! (see the Design Decisions section for an explanation): //! //! ```rust //! # use chrono::{NaiveDate}; //! # use chronoutil::{RelativeDuration}; //! let one_day = RelativeDuration::days(1); //! let one_month = RelativeDuration::months(1); //! let delta = one_month + one_day; //! let start = NaiveDate::from_ymd_opt(2020, 1, 30).unwrap(); //! assert_eq!(start + delta, NaiveDate::from_ymd_opt(2020, 3, 1).unwrap()); //! ``` //! //! ### DateRule //! //! ChronoUtil provides a //! [DateRule] //! iterator to reliably generate a collection of dates at regular intervals. //! For example, the following will yield one `NaiveDate` on the last day of each //! month in 2025: //! //! ```rust //! # use chrono::NaiveDate; //! # use chronoutil::DateRule; //! let start = NaiveDate::from_ymd_opt(2025, 1, 31).unwrap(); //! let rule = DateRule::monthly(start).with_count(12); //! // 2025-1-31, 2025-2-28, 2025-3-31, 2025-4-30, ... //! ``` //! //! ### Shift functions //! //! ChronoUtil also exposes useful shift functions which are used internally, namely: //! //! - [shift_months] to shift a datelike value by a given number of months //! - [shift_years] to shift a datelike value by a given number of years //! - [with_day] to shift a datelike value to a given day //! - [with_month] to shift a datelike value to a given month //! - [with_year] to shift a datelike value to a given year //! //! ## Design decisions and gotchas //! //! We favour simplicity over complexity: we use only the Gregorian calendar and //! make no changes e.g. for dates before the 1500s. //! //! For days between the 1st and 28th, shifting by months has an obvious //! unambiguous meaning which we always stick to. One month after Jan 28th is //! always Feb 28th. Shifting Feb 28th by another month will give Mar 28th. //! //! When shifting a day that has no equivalent in another month (e.g. asking //! for one month after Jan 30th), we first compute the target month, and then if //! the corresponding day does not exist in that month, we take the final day of the //! month as the result. So, on a leap year, one month after Jan 30th is Feb 29th. //! //! The order of precidence for a `RelativeDuration` is as follows: //! //! 1. Work out the target month, if shifting by months //! 2. If the initial day does not exist in that month, take the final day of the month //! 3. Execute any further `Duration` shifts //! //! So a `RelativeDuration` of 1 month and 1 day applied to Jan 31st first shifts to the //! last day of Feb, and then adds a single day, giving the 1st of Mar. Applying to Jan 30th //! gives the same result. //! //! Shifted dates have no _memory_ of the date they were shifted from. Thus if we shift //! Jan 31st by one month and obtain Feb 28th, a further shift of one month will be Mar 28th, //! _not_ Mar 31st. //! //! This leads us to an interesting point about the `RelativeDuration`: addition is not //! _associative_: //! //! ```rust //! # use chrono::NaiveDate; //! # use chronoutil::RelativeDuration; //! //! let d1 = (NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() + RelativeDuration::months(1)) //! + RelativeDuration::months(1); //! let d2 = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() //! + (RelativeDuration::months(1) + RelativeDuration::months(1)); //! " } ], "description": "The main documentation and crate-level examples for chronoutil, showing RelativeDuration, DateRule, and shift functions. It includes the non-associative example of adding months to Jan 31.", "language": "rust", "title": "Chronoutil lib.rs - Overview and Examples" } ], "pageDescription": "Documentation for the chronoutil 0.2.7 Rust crate, covering RelativeDuration, DateRule, shift functions, and design decisions.", "pageSummary": "The page is the crate-level documentation for chronoutil, a Rust library that extends Chrono with RelativeDuration (month/year aware durations), DateRule iterators, and helper shift functions. It explains the semantics of shifting dates, including edge cases and non-associativity of addition.", "pageTitle": "chronoutil - Crate Documentation" } ``` ```rust #![warn(missing_docs)] //! # Chronoutil provides powerful extensions to rust's Chrono crate //! //! ChronoUtil provides the following utilities: //! - `RelativeDuration`: extending Chrono's `Duration` to add months and years //! - `DateRule`: useful iterators yielding regular (e.g. monthly) dates //! - Procedural helper functions for shifting datelike values by months and years //! //! It is heavily inspired by Python's [dateutil](https://github.com/dateutil/dateutil) //! and provides a similar API, but with less of the niche functionality. //! ## Overview //! //! ### RelativeDuration //! //! ChronoUtils uses a [RelativeDuration] type to represent the magnitude of a time span //! which may not be absolute (i.e. which is not simply a fixed number of nanoseconds). //! A relative duration is made up of a number of months together with an absolute duration //! component. //! //! ```rust //! # use chrono::{NaiveDate}; //! # use chronoutil::{RelativeDuration}; //! let one_day = RelativeDuration::days(1); //! let one_month = RelativeDuration::months(1); //! let delta = one_month + one_day; //! let start = NaiveDate::from_ymd_opt(2020, 1, 1).unwrap(); //! assert_eq!(start + delta, NaiveDate::from_ymd_opt(2020, 2, 2).unwrap()); //! ``` //! //! The behaviour of `RelativeDuration` is consistent and well-defined in edge-cases //! (see the Design Decisions section for an explanation): //! //! ```rust //! # use chrono::{NaiveDate}; //! # use chronoutil::{RelativeDuration}; //! let one_day = RelativeDuration::days(1); //! let one_month = RelativeDuration::months(1); //! let delta = one_month + one_day; //! let start = NaiveDate::from_ymd_opt(2020, 1, 30).unwrap(); //! assert_eq!(start + delta, NaiveDate::from_ymd_opt(2020, 3, 1).unwrap()); //! ``` //! //! ### DateRule //! //! ChronoUtil provides a //! [DateRule] //! iterator to reliably generate a collection of dates at regular intervals. //! For example, the following will yield one `NaiveDate` on the last day of each //! month in 2025: //! //! ```rust //! # use chrono::NaiveDate; //! # use chronoutil::DateRule; //! let start = NaiveDate::from_ymd_opt(2025, 1, 31).unwrap(); //! let rule = DateRule::monthly(start).with_count(12); //! // 2025-1-31, 2025-2-28, 2025-3-31, 2025-4-30, ... //! ``` //! //! ### Shift functions //! //! ChronoUtil also exposes useful shift functions which are used internally, namely: //! //! - [shift_months] to shift a datelike value by a given number of months //! - [shift_years] to shift a datelike value by a given number of years //! - [with_day] to shift a datelike value to a given day //! - [with_month] to shift a datelike value to a given month //! - [with_year] to shift a datelike value to a given year //! //! ## Design decisions and gotchas //! //! We favour simplicity over complexity: we use only the Gregorian calendar and //! make no changes e.g. for dates before the 1500s. //! //! For days between the 1st and 28th, shifting by months has an obvious //! unambiguous meaning which we always stick to. One month after Jan 28th is //! always Feb 28th. Shifting Feb 28th by another month will give Mar 28th. //! //! When shifting a day that has no equivalent in another month (e.g. asking //! for one month after Jan 30th), we first compute the target month, and then if //! the corresponding day does not exist in that month, we take the final day of the //! month as the result. So, on a leap year, one month after Jan 30th is Feb 29th. //! //! The order of precidence for a `RelativeDuration` is as follows: //! //! 1. Work out the target month, if shifting by months //! 2. If the initial day does not exist in that month, take the final day of the month //! 3. Execute any further `Duration` shifts //! //! So a `RelativeDuration` of 1 month and 1 day applied to Jan 31st first shifts to the //! last day of Feb, and then adds a single day, giving the 1st of Mar. Applying to Jan 30th //! gives the same result. //! //! Shifted dates have no _memory_ of the date they were shifted from. Thus if we shift //! Jan 31st by one month and obtain Feb 28th, a further shift of one month will be Mar 28th, //! _not_ Mar 31st. //! //! This leads us to an interesting point about the `RelativeDuration`: addition is not //! _associative_: //! //! ```rust //! # use chrono::NaiveDate; //! # use chronoutil::RelativeDuration; //! //! let d1 = (NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() + RelativeDuration::months(1)) //! + RelativeDuration::months(1); //! let d2 = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() //! + (RelativeDuration::months(1) + RelativeDuration::months(1)); //! `` ``` -------------------------------- ### Iterate dates with DateRule Source: https://docs.rs/chronoutil/latest/src/chronoutil/lib.rs.html?search= Shows how to use DateRule to generate a series of shifted dates, handling month-end subtleties. The example creates a rule starting at 2020-01-31 with a monthly delta and asserts the next three dates. ```rust use chrono::NaiveDate; use chronoutil::{RelativeDuration, DateRule}; let start = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap(); let delta = RelativeDuration::months(1); let mut rule = DateRule::new(start, delta); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 1, 31).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); ``` -------------------------------- ### with_day usage example Source: https://docs.rs/chronoutil/latest/chronoutil/delta/fn.with_day.html Example showing how with_day shifts a date to a given day. For February 2020, day 31 is shifted back to the 29th, and day 42 returns None. ```rust let start = NaiveDate::from_ymd_opt(2020, 2, 1).unwrap(); assert_eq!(with_day(start, 31), NaiveDate::from_ymd_opt(2020, 2, 29)); assert_eq!(with_day(start, 42), None); ``` -------------------------------- ### DateRule monthly iterator example Source: https://docs.rs/chronoutil Shows how to create a DateRule that yields the last day of each month for 12 months starting from 2025-01-31. The comment indicates the expected sequence: 2025-1-31, 2025-2-28, 2025-3-31, 2025-4-30, ... ```rust let start = NaiveDate::from_ymd_opt(2025, 1, 31).unwrap(); let rule = DateRule::monthly(start).with_count(12); // 2025-1-31, 2025-2-28, 2025-3-31, 2025-4-30, ... ``` -------------------------------- ### DateRule example with RelativeDuration Source: https://docs.rs/chronoutil/latest/src/chronoutil/lib.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows the DateRule example with RelativeDuration::months(1) from 2020-01-31 producing 2020-01-31, 2020-02-29, and 2020-03-31. Assumes chrono and chronoutil are available. The library exports RelativeDuration, DateRule, and several date-shifting utilities. ```rust //! assert_eq!(d1, NaiveDate::from_ymd_opt(2020, 3, 29).unwrap()); //! assert_eq!(d2, NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); //! ``` ``` ```rust //! ```rust //! # use chrono::NaiveDate; //! # use chronoutil::{RelativeDuration, DateRule}; //! let start = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap(); //! let delta = RelativeDuration::months(1); //! let mut rule = DateRule::new(start, delta); //! assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 1, 31).unwrap()); //! assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap()); //! assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); //! ``` ``` ```rust extern crate chrono; pub mod delta; pub mod relative_duration; pub mod rule; pub use relative_duration::RelativeDuration; pub use rule::DateRule; // Utility functions may be useful for others pub use delta::{is_leap_year, shift_months, shift_years, with_day, with_month, with_year}; ``` -------------------------------- ### Iterate shifted dates with DateRule Source: https://docs.rs/chronoutil/latest/src/chronoutil/lib.rs.html?search=u32+-%3E+bool Shows how to use DateRule to generate a series of dates shifted by a RelativeDuration, handling month-end overflow automatically. The example creates a DateRule from a start date and delta, then calls next() to get successive dates. ```rust //! # use chrono::NaiveDate; //! # use chronoutil::{RelativeDuration, DateRule}; //! let start = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap(); //! let delta = RelativeDuration::months(1); //! let mut rule = DateRule::new(start, delta); //! assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 1, 31).unwrap()); //! assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap()); //! assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); //! ``` ``` -------------------------------- ### with_year example: assert_eq!(with_year(start, 2021), NaiveDate::from_ymd_opt(2021, 2, 28).unwrap()); Source: https://docs.rs/chronoutil/latest/src/chronoutil/delta.rs.html Shows how to use `with_year` to set the year of a date, clamping to the last valid day of the month (e.g., February 28 for non-leap years). The example is from the doc comment of `with_year`. ```rust /// assert_eq!(with_year(start, 2021), NaiveDate::from_ymd_opt(2021, 2, 28).unwrap()); /// ``` ``` -------------------------------- ### Test DateRule monthly with datetime and count Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html?search=std%3A%3Avec Tests DateRule::monthly with a NaiveDateTime start, verifying that the iterator starts at the initial datetime and increments by months. The test uses a start date of 2020-01-30 and expects 5 items. ```rust // Months let interesting = NaiveDate::from_ymd_opt(2020, 1, 30).unwrap(); // The day will change each month let istart = NaiveDateTime::new(interesting, o_clock); let months: Vec = DateRule::monthly(istart).with_count(5).collect(); assert_eq!( months[0], istart, ``` -------------------------------- ### Test module for DateRule with date Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html?search=std%3A%3Avec Contains a test that verifies DateRule::secondly and DateRule::minutely with a start date and count. The test checks that the first day's dates equal the start date and the second day's dates equal start plus one day. ```rust #[cfg(test)] mod tests { use super::*; use chrono::{Duration, NaiveDateTime, NaiveTime}; #[test] fn test_rrule_with_date() { let start = NaiveDate::from_ymd_opt(2020, 1, 1).unwrap(); // Seconds, hours, minutes etc for (i, date) in DateRule::secondly(start) .with_count(24 * 60 * 60 * 2) .enumerate() { if i < 24 * 60 * 60 { assert_eq!(date, start, "Expected {} seconds to be on first day", i); } else { assert_eq!( date, start + Duration::days(1), "Expected {} seconds to be on second day", i ); } } for (i, date) in DateRule::minutely(start) .with_count(24 * 60 * 2) .enumerate() { if i < 24 * 60 { assert_eq!(date, start, "Expected {} minutes to be on first day", i); } else { assert_eq!( date, start + Duration::days(1), "Expected {} minutes to be on second day", i ); } } } } ``` -------------------------------- ### with_month usage example Source: https://docs.rs/chronoutil/latest/chronoutil/delta/fn.with_month.html Example usage of `with_month` showing that ambiguous month-ends are shifted backwards (January 31 to February 29 in 2020) and that an out-of-range month returns `None`. ```rust let start = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap(); assert_eq!(with_month(start, 2), NaiveDate::from_ymd_opt(2020, 2, 29)); assert_eq!(with_month(start, 13), None); ``` -------------------------------- ### Example usage of with_year with February 29 Source: https://docs.rs/chronoutil/latest/chronoutil/delta/fn.with_year.html Example showing that `with_year` shifts February 29 to February 28 when the target year is not a leap year. ```rust let start = NaiveDate::from_ymd_opt(2020, 2, 29).unwrap(); assert_eq!(with_year(start, 2021), NaiveDate::from_ymd_opt(2021, 2, 28).unwrap()); ``` -------------------------------- ### Test monthly DateRule with end date Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html?search=std%3A%3Avec Verifies that a monthly DateRule starting on 2020-01-30 with an end date of 2020-03-30 produces three dates, handling February correctly and preserving the time component. ```rust assert_eq!( months[1].date(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap(), "DateRule should handle Feb" ); assert_eq!(months[1].time(), o_clock, "Time should remain the same"); assert_eq!( months[2].date(), NaiveDate::from_ymd_opt(2020, 3, 30).unwrap(), "DateRule should not loose days" ); assert_eq!(months[2].time(), o_clock, "Time should remain the same"); ``` -------------------------------- ### Test long-running DateRule with various start months Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html Sanity tests for long-running monthly rules (forward and backward) across start months with 31 days, checking day values for January and April over 120 iterations. ```rust // Sanity tests for long-running shifts with various start months for month in &[1, 3, 5, 7, 8, 10, 12] { let start = NaiveDate::from_ymd_opt(2020, *month as u32, 31).unwrap(); let mut rule = DateRule::monthly(start); for _ in 0..120 { let shifted = rule.next().unwrap(); if shifted.month() == 1 { assert_eq!(shifted.day(), 31) } else if shifted.month() == 4 { assert_eq!(shifted.day(), 30) } } let freq = RelativeDuration::months(-1); let mut rule = DateRule::new(start, freq); for _ in 0..120 { let shifted = rule.next().unwrap(); if shifted.month() == 1 { assert_eq!(shifted.day(), 31) } else if shifted.month() == 4 { assert_eq!(shifted.day(), 30) } } } ``` -------------------------------- ### DateRule with custom RelativeDuration Source: https://docs.rs/chronoutil Shows how to create a DateRule with a custom RelativeDuration (one month) and iterate it. The example asserts that the rule yields Jan 31, then Feb 29 (leap year), then Mar 31, demonstrating that DateRule handles month-end subtleties. ```rust let start = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap(); let delta = RelativeDuration::months(1); let mut rule = DateRule::new(start, delta); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 1, 31).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap()); assert_eq!(rule.next().unwrap(), NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); ``` -------------------------------- ### RelativeDuration basic usage: adding months and days Source: https://docs.rs/chronoutil Shows how to create a RelativeDuration from days and months, combine them, and add to a NaiveDate. The example asserts that adding one month and one day to 2020-01-01 yields 2020-02-02. ```rust let one_day = RelativeDuration::days(1); let one_month = RelativeDuration::months(1); let delta = one_month + one_day; let start = NaiveDate::from_ymd_opt(2020, 1, 1).unwrap(); assert_eq!(start + delta, NaiveDate::from_ymd_opt(2020, 2, 2).unwrap()); ``` -------------------------------- ### Shift dates with RelativeDuration::months Source: https://docs.rs/chronoutil/latest/src/chronoutil/lib.rs.html?search= Shows how to add months to a date using RelativeDuration::months, with the result clamped to the last day of the target month. The example uses NaiveDate::from_ymd_opt and asserts the shifted dates. ```rust use chrono::NaiveDate; use chronoutil::RelativeDuration; let d1 = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() + RelativeDuration::months(1); let d2 = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() + RelativeDuration::months(2); assert_eq!(d1, NaiveDate::from_ymd_opt(2020, 2, 29).unwrap()); assert_eq!(d2, NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); ``` -------------------------------- ### Format RelativeDuration to ISO 8601 string Source: https://docs.rs/chronoutil/latest/chronoutil/relative_duration/struct.RelativeDuration.html?search= Example for RelativeDuration::format_to_iso8601, formatting RelativeDuration::years(1) and asserting it equals "P1Y". ```rust use chronoutil::RelativeDuration; assert_eq!( RelativeDuration::years(1).format_to_iso8601(), "P1Y", ); ``` -------------------------------- ### take Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=std%3A%3Avec Creates an iterator that yields the first `n` elements, or fewer if the underlying iterator ends sooner. This is a standard iterator adapter available on DateRule. ```APIDOC ## take ### Description Creates an iterator that yields the first `n` elements, or fewer if the underlying iterator ends sooner. This is a standard iterator adapter available on DateRule. ### Method take ### Signature fn take(self, n: usize) -> Take ⓘ where Self: Sized, ### Parameters - **n** (usize) - Required - The number of elements to take. ### Return Value - **Take** - An iterator that yields the first n elements. ``` -------------------------------- ### partition Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Consumes an iterator, creating two collections from it. ```APIDOC ## partition ### Description Consumes an iterator, creating two collections from it. ### Method partition ### Signature fn partition(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend, F: FnMut(&Self::Item) -> bool, ### Parameters - **f** (F) - Required - A predicate that determines which collection each item goes into. ### Returns - **(B, B)** - A tuple of two collections. ``` -------------------------------- ### pub fn with_year_opt(date: D, year: i32) -> Option Source: https://docs.rs/chronoutil/latest/chronoutil/delta/fn.with_year_opt.html Returns a new date with the year replaced by the given year, or `None` if the resulting date/time is ambiguous or non-existent (e.g., during a DST transition). ```APIDOC ## Function: with_year_opt ### Description Same as `with_year` except fallible on unresolvable dates/times. Returns `None` rather than panicking when shift results in an ambiguous or non-existing date/time (e.g. in a DST transition). ### Signature ```rust pub fn with_year_opt(date: D, year: i32) -> Option ``` ### Parameters - **date** (D) - The input date. - **year** (i32) - The year to set. ### Return Value - **Option** - The resulting date if valid, otherwise `None`. ``` -------------------------------- ### DateRule::new Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html Creates a new DateRule from an initial date and a relative duration. ```APIDOC ## DateRule::new ### Description Creates a new `DateRule` from an initial date and relative duration. ### Method `pub fn new(start: D, freq: RelativeDuration) -> Self` ### Parameters - `start` (D) - The initial date for the rule. - `freq` (RelativeDuration) - The relative duration between successive dates. ### Returns - `Self` - A new `DateRule` instance. ``` -------------------------------- ### by_ref Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates a “by reference” adapter for this instance of Iterator. ```APIDOC ## by_ref ### Description Creates a “by reference” adapter for this instance of `Iterator`. ### Method by_ref ### Signature fn by_ref(&mut self) -> &mut Self where Self: Sized, ### Returns - **&mut Self** - A mutable reference to the iterator. ``` -------------------------------- ### partition Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=std%3A%3Avec Consumes an iterator, creating two collections from it. This is a standard iterator adapter available on DateRule. ```APIDOC ## partition ### Description Consumes an iterator, creating two collections from it. This is a standard iterator adapter available on DateRule. ### Method partition ### Signature fn partition(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend, F: FnMut(&Self::Item) -> bool, ### Parameters - **f** (F) - Required - A closure that takes a reference to an item and returns a bool. ### Return Value - **(B, B)** - A tuple of two collections: one for items where f returns true, and one for items where f returns false. ``` -------------------------------- ### with_year_opt Source: https://docs.rs/chronoutil/latest/chronoutil/delta/index.html Same as `with_year` except fallible on unresolvable dates/times. ```APIDOC ## with_year_opt ### Description Same as `with_year` except fallible on unresolvable dates/times. ### Function Signature `with_year_opt(date: NaiveDate, year: i32) -> Option` ### Parameters - **date** (NaiveDate) - Required - The date to shift. - **year** (i32) - Required - The year to set. ### Return Value - **Option** - `Some` with the shifted date, or `None` if the date is unresolvable. ``` -------------------------------- ### Test DateRule edge cases: zero count and end dates Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html Tests DateRule::daily with zero count and with an end equal to start, expecting empty results. Includes commented-out code for end before start with a TODO note. ```rust let start = NaiveDate::from_ymd_opt(2020, 1, 1).unwrap(); // Zero count let mut dates: Vec = DateRule::daily(start).with_count(0).collect(); assert_eq!(dates.len(), 0); // End equals start dates = DateRule::daily(start).with_end(start).collect(); assert_eq!(dates.len(), 0); // End before start // TODO: the only way to know to stop is to determine the forward/backwardness of the duration. // This is a concept which is ill formed (e.g. +1 month - 30 days) so needs thought. // dates = DateRule::daily(start).with_end(start - Duration::days(1)).collect(); // assert_eq!(dates.len(), 0); ``` -------------------------------- ### product Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Iterates over the entire iterator, multiplying all the elements. ```APIDOC ## product ### Description Iterates over the entire iterator, multiplying all the elements. ### Signature fn product

(self) -> P where Self: Sized, P: Product, ### Returns - **P** - The product of all elements. ``` -------------------------------- ### product Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Iterates over the entire iterator, multiplying all the elements. ```APIDOC ## product ### Description Iterates over the entire iterator, multiplying all the elements. ### Signature fn product

(self) -> P ### Type Constraints - Self: Sized - P: Product ``` -------------------------------- ### Iterator for DateRule>::step_by Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Creates an iterator starting at the same point, but stepping by the given amount at each iteration. ```APIDOC ## Iterator for DateRule>::step_by ### Description Creates an iterator starting at the same point, but stepping by the given amount at each iteration. ### Method step_by ### Signature fn step_by(self, step: usize) -> StepBy where Self: Sized ### Parameters - **step** (usize) - Required - The step amount. ### Returns - **StepBy** - An iterator that steps by the given amount. ``` -------------------------------- ### product Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Iterates over the entire iterator, multiplying all the elements. ```APIDOC ## product ### Description Iterates over the entire iterator, multiplying all the elements. ### Method product ### Signature fn product

(self) -> P where Self: Sized, P: Product, ### Returns - **P** - The product of all elements in the iterator. ``` -------------------------------- ### Parse ISO 8601 duration string into RelativeDuration Source: https://docs.rs/chronoutil/latest/chronoutil/relative_duration/struct.RelativeDuration.html?search= Example for RelativeDuration::parse_from_iso8601, parsing "P1Y" and asserting it equals RelativeDuration::years(1). ```rust use chronoutil::RelativeDuration; assert_eq!( RelativeDuration::parse_from_iso8601("P1Y").unwrap(), RelativeDuration::years(1), ); ``` -------------------------------- ### product Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search= Iterates over the entire iterator, multiplying all the elements. ```APIDOC ## product ### Description Iterates over the entire iterator, multiplying all the elements. ### Method product ### Signature fn product

(self) -> P ### Constraints where Self: Sized, P: Product ``` -------------------------------- ### Test module imports and leap year test Source: https://docs.rs/chronoutil/latest/src/chronoutil/delta.rs.html Test module setup with imports and a test that verifies `is_leap_year` against a known set of leap years from 1900 to 2020. ```rust #[cfg(test)] mod tests { use std::collections::HashSet; use chrono::{ naive::{NaiveDate, NaiveDateTime, NaiveTime}, LocalResult, TimeZone, }; use super::*; #[test] fn test_leap_year_cases() { let _leap_years: Vec = vec![ 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, ]; let leap_years_1900_to_2020: HashSet = _leap_years.into_iter().collect(); for year in 1900..2021 { assert_eq!(is_leap_year(year), leap_years_1900_to_2020.contains(&year)) } } ``` -------------------------------- ### Return DateRule with rolling day set Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Part of a method that returns a new DateRule with a rolling day set, preserving existing frequency, start, end, count, and current count fields. ```rust Ok(Self { freq: self.freq, start: self.start, end: self.end, count: self.count, rolling_day: Some(rolling_day), _current_count: self._current_count, }) ``` -------------------------------- ### PartialEq for DateRule Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=u32+-%3E+bool Equality and inequality operators for DateRule instances. ```APIDOC ## PartialEq for DateRule ### Description Implements equality comparison for DateRule. ### Methods #### eq ```rust fn eq(&self, other: &DateRule) -> bool ``` Equality operator `==`. #### ne ```rust fn ne(&self, other: &Rhs) -> bool ``` Inequality operator `!=`. ``` -------------------------------- ### Test monthly DateRule with count and assertions Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html Tests DateRule::monthly with a count of 5, verifying the start date, handling of February (leap year), and that time remains unchanged. Uses NaiveDateTime and NaiveDate. ```rust let months: Vec = DateRule::monthly(istart).with_count(5).collect(); assert_eq!( months[0], istart, "DateRule should start at the initial day" ); assert_eq!( months[1].date(), NaiveDate::from_ymd_opt(2020, 2, 29).unwrap(), "DateRule should handle Feb" ); assert_eq!(months[1].time(), o_clock, "Time should remain the same"); assert_eq!( months[2].date(), NaiveDate::from_ymd_opt(2020, 3, 30).unwrap(), "DateRule should not loose days" ); assert_eq!(months[2].time(), o_clock, "Time should remain the same"); ``` -------------------------------- ### inspect Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=std%3A%3Avec Does something with each element of an iterator, passing the value on. This is a standard iterator adapter available on DateRule. ```APIDOC ## inspect ### Description Does something with each element of an iterator, passing the value on. This is a standard iterator adapter available on DateRule. ### Method inspect ### Signature fn inspect(self, f: F) -> Inspect ⓘ where Self: Sized, F: FnMut(&Self::Item), ### Parameters - **f** (F) - Required - A closure that takes a reference to an item. ### Return Value - **Inspect** - An iterator that calls f on each element and yields the original items. ``` -------------------------------- ### shift_months panics on DST forward transition Source: https://docs.rs/chronoutil/latest/src/chronoutil/delta.rs.html?search=std%3A%3Avec Demonstrates that shift_months panics when the target month is non-existent due to a DST forward transition. The example uses the Australia/Melbourne timezone on 2020-09-04 at 02:00, which is skipped when clocks advance to 03:00. ```rust if let LocalResult::Single(base) = dst_tz.with_ymd_and_hms(2020, 9, 4, 2, 00, 0) { shift_months(base, 1); // panics } ``` -------------------------------- ### with_year_opt Source: https://docs.rs/chronoutil/latest/chronoutil/delta/fn.with_year_opt.html?search= Attempts to set the year on a given date, returning `None` if the resulting date/time is ambiguous or non-existing (e.g., during a DST transition). ```APIDOC ## Function with_year_opt ### Description Same as `with_year` except fallible on unresolvable dates/times. Returns `None` rather than panicking when shift results in an ambiguous or non-existing date/time (e.g. in a DST transition). ### Signature ```rust pub fn with_year_opt(date: D, year: i32) -> Option ``` ### Parameters - **date** (D) - Required - The date to modify. - **year** (i32) - Required - The year to set. ### Return Value - **Option** - `Some(date)` if the resulting date is valid, `None` if the shift results in an ambiguous or non-existing date/time. ``` -------------------------------- ### Test with_month: forward and backward shifts Source: https://docs.rs/chronoutil/latest/src/chronoutil/delta.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Tests the with_month function. Verifies that shifting to month 13 returns None, and that backward shifts (from February to January) work correctly. ```rust ); assert_eq!(with_month(base, 13), None); // Backwards shifts work too assert_eq!( with_month( tz.with_ymd_and_hms(2021, 2, 15, 0, 0, 0).single().unwrap(), 1 ), Some(tz.with_ymd_and_hms(2021, 1, 15, 0, 0, 0).single().unwrap()) ); } ``` -------------------------------- ### Test DateRule weekly with end date Source: https://docs.rs/chronoutil/latest/src/chronoutil/rule.rs.html?search=std%3A%3Avec Tests DateRule::weekly with with_end, verifying that the iterator starts at the initial day, increments by weeks, and stops before the end date. The test uses a finish date of 2020-01-29 and expects 4 items. ```rust let finish = NaiveDate::from_ymd_opt(2020, 1, 29).unwrap(); let weeks: Vec = DateRule::weekly(start).with_end(finish).collect(); assert_eq!(weeks[0], start, "DateRule should start at the initial day"); assert_eq!( weeks[1], start + Duration::days(7), "DateRule should increment in weeks" ); assert_eq!( weeks.len(), 4, "DateRule should finish before the final day" ); ``` -------------------------------- ### RelativeDuration non-associativity example Source: https://docs.rs/chronoutil Illustrates that RelativeDuration addition is not associative. Shifting Jan 31 by one month twice yields Mar 29, while shifting by a combined two-month duration yields Mar 31, due to the lack of memory of the original day. ```rust let d1 = (NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() + RelativeDuration::months(1)) + RelativeDuration::months(1); let d2 = NaiveDate::from_ymd_opt(2020, 1, 31).unwrap() + (RelativeDuration::months(1) + RelativeDuration::months(1)); assert_eq!(d1, NaiveDate::from_ymd_opt(2020, 3, 29).unwrap()); assert_eq!(d2, NaiveDate::from_ymd_opt(2020, 3, 31).unwrap()); ``` -------------------------------- ### inspect Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Does something with each element of an iterator, passing the value on. ```APIDOC ## inspect ### Description Does something with each element of an iterator, passing the value on. ### Method inspect ### Signature fn inspect(self, f: F) -> Inspect ⓘ where Self: Sized, F: FnMut(&Self::Item), ### Parameters - **f** (F) - Required - A closure that takes a reference to each item. ### Returns - **Inspect** - A new iterator. ``` -------------------------------- ### pub fn with_rolling_day(&self, rolling_day: u32) -> Result Source: https://docs.rs/chronoutil/latest/chronoutil/rule/struct.DateRule.html?search=std%3A%3Avec Sets the rolling day for the DateRule and returns a new DateRule or an error if the day is invalid. ```APIDOC ## pub fn with_rolling_day(&self, rolling_day: u32) -> Result ### Description Sets the rolling day for the DateRule. Returns a new DateRule with the specified rolling day, or an error if the day is invalid. ### Method with_rolling_day ### Parameters - **rolling_day** (u32) - Required - The day of the month to use as the rolling day. ### Return Value - **Result** - Ok containing the updated DateRule, or Err with an error message if the rolling day is invalid. ```