Add Years (ParsiDateTime) - jalalvandi/ParsiDate GitHub Wiki

Method add_years (on ParsiDateTime)

Adds a specified number of years to 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 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 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::add_years method. Please refer to its documentation for full details on the leap day clamping logic.

Arguments

  • years: The number of years 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 starting ParsiDateTime is valid and the underlying ParsiDate::add_years call succeeds, returns the new ParsiDateTime instance (with updated date (potentially clamped day) and original time) wrapped in Ok.
  • Err(DateError::...): Returns an error if either of the following occurs:
    1. The starting ParsiDateTime instance itself holds invalid data (e.g., invalid date or time components, potentially from unsafe creation). An internal validity check might be performed first.
    2. The delegated call to ParsiDate::add_years fails. This propagates errors like DateError::InvalidDate (if the underlying date part was invalid, including the case where leap day clamping is needed but the starting date was somehow invalid) or DateError::ArithmeticOverflow (if the resulting date's year falls outside the supported range [1, 9999]).

Examples (Rust)

use parsidate::{ParsiDateTime, ParsiDate, DateError}; // Assuming these types exist

// Example 1: Leap Day Handling (Adding Years)
let dt_leap_day = ParsiDateTime::new(1403, 12, 30, 10, 0, 0).unwrap(); // Esfand 30th, 1403 (leap)
// Add 1 year -> Target year 1404 is common. Day must be clamped from 30 to 29.
let dt_next_year = dt_leap_day.add_years(1);
assert!(dt_next_year.is_ok());
let dt_next_year_unwrapped = dt_next_year.unwrap();
// Check the date part: Day clamped to 29
assert_eq!(dt_next_year_unwrapped.date(), ParsiDate::new(1404, 12, 29).unwrap()); // Expected date: 1404-12-29
// Check that the time part is unchanged
assert_eq!(dt_next_year_unwrapped.hour(), 10);
assert_eq!(dt_next_year_unwrapped.minute(), 0);
assert_eq!(dt_next_year_unwrapped.second(), 0);

// Example 2: Adding years, target is also leap (no clamping)
// Add 5 years to 1403 -> 1408 (1408 % 33 = 22 -> leap)
let dt_plus_5y = dt_leap_day.add_years(5);
assert!(dt_plus_5y.is_ok());
let dt_plus_5y_unwrapped = dt_plus_5y.unwrap();
// Date should remain Esfand 30th as 1408 is leap
assert_eq!(dt_plus_5y_unwrapped.date(), ParsiDate::new(1408, 12, 30).unwrap()); // Expected date: 1408-12-30
// Check time
assert_eq!(dt_plus_5y_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.add_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: Leap Day Handling (Subtracting Years)
let dt_leap_day_1408 = ParsiDateTime::new(1408, 12, 30, 11, 22, 33).unwrap(); // Esfand 30th, 1408 (leap)
// Subtract 1 year -> Target year 1407 (1407 % 33 = 21 -> common). Day must clamp.
let dt_minus_1y = dt_leap_day_1408.add_years(-1);
assert!(dt_minus_1y.is_ok());
let dt_minus_1y_unwrapped = dt_minus_1y.unwrap();
// Check date part: Day clamped to 29
assert_eq!(dt_minus_1y_unwrapped.date(), ParsiDate::new(1407, 12, 29).unwrap()); // Expected date: 1407-12-29
// Check time part
assert_eq!(dt_minus_1y_unwrapped.time(), (11, 22, 33));

// 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_years(-1); // Attempt to go to year 0
assert!(result.is_err());
// assert_eq!(result, Err(DateError::ArithmeticOverflow));