Sub Years - parsicore/parsidate GitHub Wiki
sub_years
Method Subtracts a specified number of years from this ParsiDate
, returning a new ParsiDate
.
Description
This method provides a convenient way to calculate the date that occurs exactly a given number of years before the current ParsiDate
instance.
It functions as a direct equivalent to calling the add_years
method with a negative value for the number of years (i.e., self.add_years(-years_to_sub)
if add_years
accepted negative values, or uses the same internal logic adapted for subtraction).
The calculation involves decrementing the year component. A crucial behavior occurs when the original date is the leap day (Esfand 30th) and the target year (after subtraction) is a common year: the day is adjusted downwards (clamped) to the 29th of Esfand to form a valid date in the target common year.
Arguments
years_to_sub
: The non-negative number of years (u32
or similar unsigned integer type) to subtract from the current date's year.
Returns
Ok(ParsiDate)
: If the subtraction results in a valid date within the supported range of the library (typically years 1 to 9999), returns the newParsiDate
instance wrapped inOk
. Note the potential day clamping for leap day transitions.Err(DateError::...)
: Returns an error under the same conditions as theadd_years
method (when performing the equivalent addition of a negative number). This primarily occurs if:- The resulting year falls outside the supported year range (e.g., subtracting years from an early date results in a year less than 1).
- An arithmetic overflow or other internal error occurs (unlikely for simple year subtraction). Refer to
add_years
documentation for specific error kinds.
Leap Day Handling (Day Clamping)
If the original date is Esfand 30th (which only exists in a leap year) and subtracting years_to_sub
results in a target year that is a common year, the day component of the resulting ParsiDate
will be adjusted from 30 down to 29 (the last day of Esfand in a common year).
- Example: Subtracting 1 year from
1403-12-30
(Esfand 30th of a leap year). The target year is 1402, which is a common year. Esfand 30th is invalid in 1402, so the result is clamped to1402-12-29
.
If the target year is also a leap year, or if the original date was not Esfand 30th, the day remains unchanged.
Examples (Rust)
use parsidate::{ParsiDate, DateError}; // Assuming these types exist
// --- Example with Leap Day Clamping ---
let leap_day = ParsiDate::new(1403, 12, 30).unwrap(); // Esfand 30th in leap year 1403
// Subtract 1 year. Target year 1402 is common.
// Day must be clamped from 30 down to 29.
assert_eq!(
leap_day.sub_years(1),
Ok(ParsiDate::new(1402, 12, 29).unwrap()) // -> 1402-12-29
);
// --- Subtracting years where target is also leap (no clamping needed) ---
let leap_day_1407 = ParsiDate::new(1407, 12, 30).unwrap(); // 1407 is leap (1407 % 33 = 21 -> NO, 1407 % 33 = 21 -> Not leap, let's use 1408)
let leap_day_1408 = ParsiDate::new(1408, 12, 30).unwrap(); // 1408 is leap (1408 % 33 = 22 -> leap)
// Subtract 5 years. Target year 1403 is leap (1403 % 33 = 17 -> leap)
// No clamping needed as target year is leap.
assert_eq!(
leap_day_1408.sub_years(5),
Ok(ParsiDate::new(1403, 12, 30).unwrap()) // -> 1403-12-30
);
// --- Simple Subtraction (not on leap day) ---
let date = ParsiDate::new(1403, 5, 15).unwrap(); // Mordad 15th, 1403
// Subtract 10 years.
assert_eq!(
date.sub_years(10),
Ok(ParsiDate::new(1393, 5, 15).unwrap()) // -> 1393-05-15
);
// --- Example Resulting in Error (Going Below Year 1) ---
let early_date = ParsiDate::new(5, 1, 1).unwrap(); // Year 5
// Subtracting 5 years results in Year 0, which is outside the supported range [1, 9999].
let result = early_date.sub_years(5);
assert!(result.is_err());
// assert_eq!(result, Err(DateError::InvalidDate)); // Or similar error
let result_exact = ParsiDate::new(1, 6, 1).unwrap().sub_years(1); // Subtracting 1 from Year 1
assert!(result_exact.is_err()); // Should fail