Sub Months (ParsiDateTime) - parsicore/parsidate GitHub Wiki
sub_months
(on ParsiDateTime)
Method Subtracts a specified number of months from 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 subtracted. The time part (hour, minute, second) of the original ParsiDateTime
instance remains unchanged in the resulting instance.
It functions as a convenient alternative to calling add_months
with a negative value (i.e., self.add_months(-months)
).
The core date calculation, including adjusting the month and year, and handling day clamping, is delegated to the corresponding ParsiDate::sub_months
method (or equivalently, ParsiDate::add_months
with a negative value). 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
method documentation for full details on this behavior.
Arguments
months
: The non-negative number of months (u32
or similar unsigned integer type) to subtract from the current date part.
Returns
Ok(ParsiDateTime)
: If the startingParsiDateTime
is valid and the underlyingParsiDate::sub_months
(or equivalent) call succeeds, returns the newParsiDateTime
instance (with updated date (potentially clamped day) and original time) wrapped inOk
.Err(DateError::...)
: Returns an error under the same conditions as theadd_months
method when called with a negative value. This occurs if:- The starting
ParsiDateTime
instance itself holds invalid data. - The delegated call to
ParsiDate::sub_months
(oradd_months
) fails. This propagates errors likeDateError::InvalidDate
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: Subtracting months without clamping
let dt = ParsiDateTime::new(1403, 1, 31, 9, 0, 0).unwrap(); // Farvardin 31st, 09:00:00
// Subtract 7 months.
// Target: 1403-01 minus 7 months = Month -6 -> wraps to Month (12 - 6) = 6 of previous year (1402).
// Target date: 1402-06-31 (Shahrivar 31st). Shahrivar has 31 days, so day 31 is valid. No clamping.
let dt_minus_7m = dt.sub_months(7);
assert!(dt_minus_7m.is_ok());
let dt_minus_7m_unwrapped = dt_minus_7m.unwrap();
// Check the date part
assert_eq!(dt_minus_7m_unwrapped.date(), ParsiDate::new(1402, 6, 31).unwrap()); // Expected: 1402-06-31
// Check that the time part is unchanged
assert_eq!(dt_minus_7m_unwrapped.hour(), 9);
assert_eq!(dt_minus_7m_unwrapped.minute(), 0);
assert_eq!(dt_minus_7m_unwrapped.second(), 0);
// Example 2: Subtracting months resulting in clamping
let dt2 = ParsiDateTime::new(1403, 3, 31, 14, 15, 16).unwrap(); // Khordad 31st, 1403
// Subtract 3 months -> Target is Esfand (Month 12) of 1402.
// Assume 1402 is a common year (Esfand has 29 days). Original day 31 > 29 -> clamp.
let dt_minus_3m = dt2.sub_months(3);
assert!(dt_minus_3m.is_ok());
let dt_minus_3m_unwrapped = dt_minus_3m.unwrap();
// Check the date part: Day clamped to 29
assert_eq!(dt_minus_3m_unwrapped.date(), ParsiDate::new(1402, 12, 29).unwrap()); // Expected: 1402-12-29
// Check time part
assert_eq!(dt_minus_3m_unwrapped.time(), (14, 15, 16));
// Example 3: Error case (resulting year out of range)
let earliest_dt = ParsiDateTime::new(1, 1, 1, 0, 0, 0).unwrap();
let result = earliest_dt.sub_months(1); // Attempt to go before year 1
assert!(result.is_err());
// assert_eq!(result, Err(DateError::ArithmeticOverflow));