Add Days - parsicore/parsidate GitHub Wiki
add_days
(on ParsiDate)
Method Adds a specified number of days to this ParsiDate
, returning a new ParsiDate
instance representing the result.
Description
This method calculates a new date by adding a given number of days to the current ParsiDate
instance (self
). The operation correctly handles transitions across month and year boundaries, including accounting for Persian leap years (specifically the length of Esfand).
The calculation is performed robustly by:
- Converting the
ParsiDate
instance (self
) into its equivalentchrono::NaiveDate
(Gregorian date). - Using
chrono
's date arithmetic to add the specified number ofdays
to theNaiveDate
. This handles Gregorian leap years and month lengths correctly. - Converting the resulting
chrono::NaiveDate
back into aParsiDate
.
The days
argument can be positive to advance the date forward or negative to move the date backward in time.
Arguments
days
: The number of days to add to the current date (i64
or a similar signed integer type compatible withchrono::Duration::days
).- A positive value moves the date forward.
- A negative value moves the date backward.
- A value of zero results in a
ParsiDate
identical to the original.
Returns
Ok(ParsiDate)
: If the startingParsiDate
is valid, the intermediate Gregorian calculations succeed, and the final resulting date falls within the supported range ofParsiDate
(typically years 1-9999), returns the newParsiDate
wrapped inOk
.Err(DateError::InvalidDate)
: If the startingParsiDate
instance (self
) represents an invalid date according to Persian calendar rules.Err(DateError::GregorianConversionError)
: If the conversion fromParsiDate
tochrono::NaiveDate
, or the conversion back from the calculatedchrono::NaiveDate
toParsiDate
, fails. This is generally unlikely for valid dates within the typical supported range but could occur in edge cases or if the underlying conversion logic encounters an unexpected issue.Err(DateError::ArithmeticOverflow)
: If adding thedays
results in achrono::NaiveDate
that falls outside the representable range ofchrono
itself (very large positive or negative dates), or if the final calculated date, when converted back toParsiDate
, falls outside the supported year range (e.g., year 0 or year 10000+).
Examples (Rust)
use parsidate::{ParsiDate, DateError}; // Assuming these types exist
// --- Basic Addition ---
let date = ParsiDate::new(1403, 12, 28).unwrap(); // 1403 is a leap year in Persian calendar
// Add days within the same month (Esfand, which has 30 days in 1403)
assert_eq!(date.add_days(1), Ok(ParsiDate::new(1403, 12, 29).unwrap()));
assert_eq!(date.add_days(2), Ok(ParsiDate::new(1403, 12, 30).unwrap())); // Hit the leap day
// Add days to cross into the next year (1404 is not a leap year)
assert_eq!(date.add_days(3), Ok(ParsiDate::new(1404, 1, 1).unwrap())); // From 1403/12/30 to 1404/01/01
assert_eq!(date.add_days(10), Ok(ParsiDate::new(1404, 1, 8).unwrap())); // 1403/12/28 + 10 days = 1404/01/08
// Add zero days
assert_eq!(date.add_days(0), Ok(ParsiDate::new(1403, 12, 28).unwrap()));
// --- Subtraction (Negative Days) ---
let date_start_of_1404 = ParsiDate::new(1404, 1, 1).unwrap();
// Subtract days to cross back into the previous year (1403 leap year)
assert_eq!(date_start_of_1404.add_days(-1), Ok(ParsiDate::new(1403, 12, 30).unwrap())); // Back to the leap day
assert_eq!(date_start_of_1404.add_days(-2), Ok(ParsiDate::new(1403, 12, 29).unwrap()));
// Subtract exactly one leap year's worth of days (366 for 1403)
assert_eq!(date_start_of_1404.add_days(-366), Ok(ParsiDate::new(1403, 1, 1).unwrap()));
// --- Error Case: Resulting Date Out of Range ---
let earliest_date = ParsiDate::new(1, 1, 1).unwrap();
// Try to subtract days to go before the supported year 1
let result_before_epoch = earliest_date.add_days(-1);
assert!(result_before_epoch.is_err());
// The specific error might be ArithmeticOverflow or GregorianConversionError depending on implementation details
// assert_eq!(result_before_epoch, Err(DateError::ArithmeticOverflow)); // Example assertion
// Try to add days resulting in a year beyond the supported range (e.g., > 9999)
// let latest_date = ParsiDate::new(9999, 10, 1).unwrap();
// let result_too_far = latest_date.add_days(365 * 2); // Add 2 years
// assert!(result_too_far.is_err());
// assert_eq!(result_too_far, Err(DateError::ArithmeticOverflow)); // Example assertion