With Month - jalalvandi/ParsiDate GitHub Wiki

Method with_month

Creates a new ParsiDate instance by replacing the month component, adjusting the day if necessary (day clamping).

Description

This method creates a new ParsiDate based on the current instance (self), but with the month component changed to the specified month value. The year component is copied directly from the original self instance.

The day component is initially copied from self.day(), but it is then subject to day clamping:

  • If the original day value is greater than the number of days allowed in the target month (within the same year), the day in the new ParsiDate is adjusted downwards to the last valid day of that target month.
    • Example: Changing month from Farvardin (31 days) to Mehr (30 days) when the original day was 31 will result in the new day being 30.
    • Example: Changing month from Ordibehesht (31 days) to Esfand (month 12) in a common year (29 days) when the original day was 30 or 31 will result in the new day being 29.

This method also performs validation to ensure the starting ParsiDate is valid and the target month is within the acceptable range [1, 12].

Arguments

  • month: The desired month for the new ParsiDate (u8 or similar integer type). Must be between 1 and 12 (inclusive).

Returns

  • Ok(ParsiDate): If the original ParsiDate (self) is valid and the target month is valid (1-12), returns the new ParsiDate instance (with potentially clamped day) wrapped in Ok.
  • Err(DateError::InvalidDate): Returns an error if either of the following conditions is met:
    1. The starting ParsiDate instance (self) is invalid (e.g., contains invalid day or month data, potentially from unsafe creation).
    2. The provided target month is outside the valid range [1, 12] (e.g., 0 or 13).

Examples (Rust)

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

let date = ParsiDate::new(1403, 1, 31).unwrap(); // Farvardin 31st, 1403 (1403 is leap)

// --- Success Cases with Clamping ---

// Change month to Mehr (Month 7, 30 days). Original day 31 is > 30, so clamped to 30.
let date_mehr = date.with_month(7);
assert!(date_mehr.is_ok());
assert_eq!(date_mehr.unwrap(), ParsiDate::new(1403, 7, 30).unwrap()); // Day becomes 30

// Change month to Esfand (Month 12). Year 1403 is leap (Esfand has 30 days).
// Original day 31 is > 30, so clamped to 30.
let date_esfand_leap = date.with_month(12);
assert!(date_esfand_leap.is_ok());
assert_eq!(date_esfand_leap.unwrap(), ParsiDate::new(1403, 12, 30).unwrap()); // Day becomes 30


// --- Success Case with Clamping (Common Year) ---
let date_common_year = ParsiDate::new(1404, 1, 31).unwrap(); // Farvardin 31st, 1404 (common)
// Change month to Esfand (Month 12). Year 1404 is common (Esfand has 29 days).
// Original day 31 is > 29, so clamped to 29.
let date_esfand_common = date_common_year.with_month(12);
assert!(date_esfand_common.is_ok());
assert_eq!(date_esfand_common.unwrap(), ParsiDate::new(1404, 12, 29).unwrap()); // Day becomes 29


// --- Success Case without Clamping ---
// Change month to Ordibehesht (Month 2, 31 days). Original day 31 is valid.
let date_ordibehesht = date.with_month(2);
assert!(date_ordibehesht.is_ok());
assert_eq!(date_ordibehesht.unwrap(), ParsiDate::new(1403, 2, 31).unwrap()); // Day remains 31


// --- Error Cases ---

// Target month 0 is out of range [1, 12]
assert_eq!(
    date.with_month(0),
    Err(DateError::InvalidDate)
);

// Target month 13 is out of range [1, 12]
assert_eq!(
    date.with_month(13),
    Err(DateError::InvalidDate)
);


// --- Error Case: Starting date is invalid ---
// Create an invalid date unsafely (e.g., invalid day 32)
let invalid_start = unsafe { ParsiDate::new_unchecked(1400, 1, 32) };
// Trying to change the month of an invalid date should fail validation
assert_eq!(
    invalid_start.with_month(2),
    Err(DateError::InvalidDate) // Original date is invalid
);