With Year - jalalvandi/ParsiDate GitHub Wiki
with_year
Method Creates a new ParsiDate
instance by replacing the year component, adjusting the day for leap day transitions if necessary.
Description
This method creates a new ParsiDate
based on the current instance (self
), but with the year component changed to the specified year
value. The month and day components are initially copied from the original self
instance.
A special handling logic is applied for the leap day (Esfand 30th):
- If the original date (
self
) is Esfand 30th (which only exists in a leap year), and the targetyear
is a common year, the day component in the newParsiDate
is automatically adjusted (clamped) down to 29. This ensures the resulting date is valid (as Esfand only has 29 days in a common year). - If the original date is Esfand 30th and the target
year
is also a leap year, the day remains 30. - If the original date is not Esfand 30th, the day component remains unchanged.
This method performs validation to ensure the starting ParsiDate
is valid and the target year
is within the acceptable range [1, 9999]. The final validity of the resulting date (after potential clamping) is ensured by the internal logic used for construction.
Arguments
year
: The desired year for the newParsiDate
(i32
or similar integer type). Must be within the range[1, 9999]
.
Returns
Ok(ParsiDate)
: If the originalParsiDate
(self
) is valid and the targetyear
is valid (1-9999), returns the newParsiDate
instance (with potentially clamped day for leap day transitions) wrapped inOk
.Err(DateError::InvalidDate)
: Returns an error if either of the following conditions is met:- The starting
ParsiDate
instance (self
) is invalid (e.g., contains invalid month or day data, potentially fromunsafe
creation). - The provided target
year
is outside the supported range [1, 9999].
- The starting
Examples (Rust)
use parsidate::{ParsiDate, DateError}; // Assuming these types exist
let date = ParsiDate::new(1403, 5, 2).unwrap(); // Mordad 2nd, 1403 (1403 is leap)
// --- Success Case: Simple Year Change ---
// Change year to 1404 (common year). Month/Day are not Esfand 30th, so no clamping.
let date_next_year = date.with_year(1404);
assert!(date_next_year.is_ok());
assert_eq!(date_next_year.unwrap(), ParsiDate::new(1404, 5, 2).unwrap());
// --- Success Cases: Leap Day Handling ---
let leap_day = ParsiDate::new(1403, 12, 30).unwrap(); // Esfand 30th, 1403 (leap)
// Change to a common year (1404). Original day is Esfand 30th. Must clamp day to 29.
let common_year_date = leap_day.with_year(1404);
assert!(common_year_date.is_ok());
assert_eq!(
common_year_date.unwrap(),
ParsiDate::new(1404, 12, 29).unwrap() // Note: Day is 29
);
// Change to another leap year (1408). Original day is Esfand 30th. Target allows Esfand 30th. No clamping.
// (Checking leap: 1408 % 33 = 22 -> leap)
let other_leap_year_date = leap_day.with_year(1408);
assert!(other_leap_year_date.is_ok());
assert_eq!(
other_leap_year_date.unwrap(),
ParsiDate::new(1408, 12, 30).unwrap() // Note: Day is 30
);
// --- Error Cases ---
// Target year 0 is out of range [1, 9999]
assert_eq!(
date.with_year(0),
Err(DateError::InvalidDate)
);
// Target year 10000 is out of range [1, 9999]
assert_eq!(
date.with_year(10000),
Err(DateError::InvalidDate)
);
// --- Error Case: Starting date is invalid ---
// Create an invalid date unsafely (e.g., invalid month 13)
let invalid_start = unsafe { ParsiDate::new_unchecked(1400, 13, 1) };
// Trying to change the year of an invalid date should fail validation
assert_eq!(
invalid_start.with_year(1401),
Err(DateError::InvalidDate) // Original date is invalid
);