Add Months (ParsiDateTime) - parsicore/parsidate GitHub Wiki
add_months
(on ParsiDateTime)
Method Adds a specified number of months to the date part of this ParsiDateTime
, returning a new ParsiDateTime
with the same time component and potentially adjusted day.
Description
This method calculates a new ParsiDateTime
by modifying only the date part (year, month, day) based on the number of months added or subtracted. The time part (hour, minute, second) of the original ParsiDateTime
instance remains unchanged in the resulting instance.
The core date calculation, including adjusting the month and year, and handling day clamping, is delegated to the corresponding ParsiDate::add_months
method. Day clamping means if the original day is invalid for the target month (e.g., day 31 when moving to Mehr), the day in the new date is adjusted to the last valid day of the target month. Please refer to the ParsiDate::add_months
documentation for full details on this behavior.
Arguments
months
: The number of months to add (i32
or similar signed integer type).- A positive value moves the date forward.
- A negative value moves the date backward.
Returns
Ok(ParsiDateTime)
: If the startingParsiDateTime
is valid and the underlyingParsiDate::add_months
call succeeds, returns the newParsiDateTime
instance (with updated date (potentially clamped day) and original time) wrapped inOk
.Err(DateError::...)
: Returns an error if either of the following occurs:- The starting
ParsiDateTime
instance itself holds invalid data (e.g., invalid date or time components, potentially fromunsafe
creation). An internal validity check might be performed first. - The delegated call to
ParsiDate::add_months
fails. This propagates errors likeDateError::InvalidDate
(if the underlying date part was invalid) orDateError::ArithmeticOverflow
(if the resulting date's year falls outside the supported range).
- The starting
Examples (Rust)
use parsidate::{ParsiDateTime, ParsiDate, DateError}; // Assuming these types exist
// Example 1: Adding months resulting in day clamping
let dt1 = ParsiDateTime::new(1403, 6, 31, 12, 0, 0).unwrap(); // Shahrivar 31st, 12:00:00
// Add 1 month -> Target is Mehr (Month 7), which only has 30 days.
let dt_plus_1m = dt1.add_months(1);
assert!(dt_plus_1m.is_ok());
let dt_plus_1m_unwrapped = dt_plus_1m.unwrap();
// Check the date part: Day should be clamped from 31 to 30.
assert_eq!(dt_plus_1m_unwrapped.date(), ParsiDate::new(1403, 7, 30).unwrap()); // Expected date: 1403-07-30
// Check that the time part is unchanged
assert_eq!(dt_plus_1m_unwrapped.hour(), 12);
assert_eq!(dt_plus_1m_unwrapped.minute(), 0);
assert_eq!(dt_plus_1m_unwrapped.second(), 0);
// Example 2: Adding months without clamping
let dt2 = ParsiDateTime::new(1403, 7, 15, 9, 45, 30).unwrap(); // Mehr 15th, 09:45:30
// Add 2 months -> Target is Azar (Month 9), which has 30 days. Day 15 is valid.
let dt_plus_2m = dt2.add_months(2);
assert!(dt_plus_2m.is_ok());
let dt_plus_2m_unwrapped = dt_plus_2m.unwrap();
// Check the date part: Day should remain 15.
assert_eq!(dt_plus_2m_unwrapped.date(), ParsiDate::new(1403, 9, 15).unwrap()); // Expected date: 1403-09-15
// Check time part
assert_eq!(dt_plus_2m_unwrapped.time(), (9, 45, 30));
// Example 3: Subtracting months across year boundary
let dt3 = ParsiDateTime::new(1404, 2, 5, 18, 0, 0).unwrap(); // Ordibehesht 5th, 1404
// Subtract 3 months -> Target is Esfand (Month 12) of 1403. Day 5 is valid.
let dt_minus_3m = dt3.add_months(-3);
assert!(dt_minus_3m.is_ok());
let dt_minus_3m_unwrapped = dt_minus_3m.unwrap();
// Check the date part
assert_eq!(dt_minus_3m_unwrapped.date(), ParsiDate::new(1403, 12, 5).unwrap()); // Expected date: 1403-12-05
// Check time part
assert_eq!(dt_minus_3m_unwrapped.time(), (18, 0, 0));
// Example 4: Subtracting months resulting in clamping (leap day involved)
let dt4 = ParsiDateTime::new(1403, 12, 30, 10, 10, 10).unwrap(); // Esfand 30th, 1403 (leap)
// Subtract 12 months -> Target is Esfand (Month 12) of 1402. 1402 is common (29 days).
// Original day 30 > 29, so must clamp.
let dt_minus_12m = dt4.add_months(-12);
assert!(dt_minus_12m.is_ok());
let dt_minus_12m_unwrapped = dt_minus_12m.unwrap();
// Check the date part: Day clamped to 29
assert_eq!(dt_minus_12m_unwrapped.date(), ParsiDate::new(1402, 12, 29).unwrap()); // Expected date: 1402-12-29
// Check time part
assert_eq!(dt_minus_12m_unwrapped.time(), (10, 10, 10));
// Example 5: Error case (resulting year out of range)
let earliest_dt = ParsiDateTime::new(1, 1, 1, 0, 0, 0).unwrap();
let result = earliest_dt.add_months(-1); // Attempt to go before year 1
assert!(result.is_err());
// assert_eq!(result, Err(DateError::ArithmeticOverflow));