Sub Years (ParsiDateTime) - parsicore/parsidate GitHub Wiki
sub_years
(on ParsiDateTime)
Method Subtracts a specified number of years from the date part of this ParsiDateTime
, returning a new ParsiDateTime
with the same time component and potentially adjusted leap day.
Description
This method calculates a new ParsiDateTime
by modifying only the date part (year, month, day) based on the number of years 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_years
with a negative value (i.e., self.add_years(-years)
).
The core date calculation, including adjusting the year and handling the leap day adjustment (clamping Esfand 30th to 29th when moving from a leap year to a common year), is delegated to the corresponding ParsiDate::sub_years
method (or equivalently, ParsiDate::add_years
with a negative value). Please refer to the ParsiDate
method documentation for full details on the leap day clamping logic.
Arguments
years
: The non-negative number of years (u32
or similar unsigned integer type) to subtract from the current date's year.
Returns
Ok(ParsiDateTime)
: If the startingParsiDateTime
is valid and the underlyingParsiDate::sub_years
(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_years
method when called with a negative value. This occurs if:- The starting
ParsiDateTime
instance itself holds invalid data. - The delegated call to
ParsiDate::sub_years
(oradd_years
) fails. This propagates errors likeDateError::InvalidDate
orDateError::ArithmeticOverflow
(if the resulting date's year falls outside the supported range [1, 9999]).
- The starting
Examples (Rust)
use parsidate::{ParsiDateTime, ParsiDate, DateError}; // Assuming these types exist
// Example 1: Leap Day Handling (Subtracting Years)
let dt_leap_day = ParsiDateTime::new(1403, 12, 30, 10, 0, 0).unwrap(); // Esfand 30th, 1403 (leap)
// Subtract 1 year -> Target year 1402 is common. Day must be clamped from 30 to 29.
let dt_prev_year_result = dt_leap_day.sub_years(1);
assert!(dt_prev_year_result.is_ok());
let dt_prev_year = dt_prev_year_result.unwrap();
// Check the date part: Day clamped to 29
assert_eq!(dt_prev_year.date(), ParsiDate::new(1402, 12, 29).unwrap()); // Expected date: 1402-12-29
// Check that the time part is unchanged
assert_eq!(dt_prev_year.hour(), 10);
assert_eq!(dt_prev_year.minute(), 0);
assert_eq!(dt_prev_year.second(), 0);
// Example 2: Subtracting years, target is also leap (no clamping)
// Subtract 5 years from 1403 -> Target is 1398 (1398 % 33 = 29 -> common). Clamp needed.
let dt_minus_5y = dt_leap_day.sub_years(5);
assert!(dt_minus_5y.is_ok());
let dt_minus_5y_unwrapped = dt_minus_5y.unwrap();
// Date should be Esfand 29th as 1398 is common
assert_eq!(dt_minus_5y_unwrapped.date(), ParsiDate::new(1398, 12, 29).unwrap()); // Expected date: 1398-12-29
// Check time
assert_eq!(dt_minus_5y_unwrapped.time(), (10, 0, 0));
// Subtract 4 years from 1403 -> Target is 1399 (1399 % 33 = 30 -> leap). No clamp needed.
let dt_minus_4y = dt_leap_day.sub_years(4);
assert!(dt_minus_4y.is_ok());
let dt_minus_4y_unwrapped = dt_minus_4y.unwrap();
// Date should be Esfand 30th as 1399 is leap
assert_eq!(dt_minus_4y_unwrapped.date(), ParsiDate::new(1399, 12, 30).unwrap()); // Expected date: 1399-12-30
// Check time
assert_eq!(dt_minus_4y_unwrapped.time(), (10, 0, 0));
// Example 3: Simple Year Subtraction (not leap day)
let dt_normal = ParsiDateTime::new(1405, 5, 15, 15, 30, 45).unwrap(); // Mordad 15th, 1405
// Subtract 10 years -> Target year 1395
let dt_minus_10y = dt_normal.sub_years(10);
assert!(dt_minus_10y.is_ok());
let dt_minus_10y_unwrapped = dt_minus_10y.unwrap();
// Check date part
assert_eq!(dt_minus_10y_unwrapped.date(), ParsiDate::new(1395, 5, 15).unwrap()); // Expected date: 1395-05-15
// Check time part
assert_eq!(dt_minus_10y_unwrapped.time(), (15, 30, 45));
// Example 4: Error case (resulting year out of range)
let earliest_dt = ParsiDateTime::new(1, 1, 1, 0, 0, 0).unwrap();
let result = earliest_dt.sub_years(1); // Attempt to go to year 0
assert!(result.is_err());
// assert_eq!(result, Err(DateError::ArithmeticOverflow));