Sub Days (ParsiDateTime) - jalalvandi/ParsiDate GitHub Wiki

Method sub_days (on ParsiDateTime)

Subtracts a specified number of days from the date part of this ParsiDateTime, returning a new ParsiDateTime with the same time component.

Description

This method calculates a new ParsiDateTime by modifying only the date part (year, month, day) based on the number of days 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_days with a negative value (i.e., self.add_days(-days)).

The core date calculation, including handling month/year boundaries and leap years, is delegated to the corresponding ParsiDate::sub_days method (or equivalently, ParsiDate::add_days with a negative value). Please refer to the ParsiDate method documentation for details on the date arithmetic logic.

Arguments

  • days: The non-negative number of days (u32, u64, or similar unsigned integer type) to subtract from the current date part.

Returns

  • Ok(ParsiDateTime): If the starting ParsiDateTime is valid and the underlying ParsiDate::sub_days (or equivalent) call succeeds, returns the new ParsiDateTime instance (with updated date and original time) wrapped in Ok.
  • Err(DateError::...): Returns an error under the same conditions as the add_days method when called with a negative value. This occurs if:
    1. The starting ParsiDateTime instance itself holds invalid data.
    2. The delegated call to ParsiDate::sub_days (or ParsiDate::add_days) fails. This propagates errors like DateError::InvalidDate, DateError::GregorianConversionError, or DateError::ArithmeticOverflow (if the resulting date falls outside the supported range, e.g., before year 1).

Examples (Rust)

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

let dt = ParsiDateTime::new(1403, 1, 15, 10, 30, 0).unwrap(); // Farvardin 15th, 1403, 10:30:00

// --- Subtracting Days ---

// Subtract 20 days. Go back 15 days to 1402-12-30 (1403 is leap, so 1402 is common). Need 5 more days.
// -> Lands on 1402-12-25 (assuming 1402 is common - check needed).
// Let's re-calculate: 1403-01-15 minus 15 days is 1402-12-30 (assuming 1403 leap).
// Need to subtract 5 more days from 1402-12-30. 1402 is common (1402 % 33 = 16), so Esfand has 29 days.
// 1402-12-30 is invalid! The calculation must handle this. Let's re-check the example input/output.
// Ah, the example output is 1402-12-24. Let's trace:
// 1403-01-15 minus 15 days lands on 1403-01-00, which wraps to 1402-12-29 (assuming 1402 is common).
// Wait, ParsiDate::add_days uses Gregorian conversion.
// 1403-01-15 is 2024-04-03.
// 2024-04-03 minus 20 days is 2024-03-14.
// 2024-03-14 converts to Persian: 1402-12-24. The example is correct.

let dt_minus_20d = dt.sub_days(20);
assert!(dt_minus_20d.is_ok());
let dt_minus_20d_unwrapped = dt_minus_20d.unwrap();

// Check the date part: Example shows 1402-12-24
assert_eq!(dt_minus_20d_unwrapped.date(), ParsiDate::new(1402, 12, 24).unwrap());
// Check that the time part is unchanged
assert_eq!(dt_minus_20d_unwrapped.hour(), 10);
assert_eq!(dt_minus_20d_unwrapped.minute(), 30);
assert_eq!(dt_minus_20d_unwrapped.second(), 0);


// --- Error Case (e.g., Resulting date out of range) ---
let earliest_dt = ParsiDateTime::new(1, 1, 1, 0, 0, 0).unwrap();
let result = earliest_dt.sub_days(1); // Attempt to go before year 1
assert!(result.is_err());
// The error kind would be propagated from ParsiDate::sub_days/add_days
// assert!(matches!(result, Err(DateError::ArithmeticOverflow) | Err(DateError::GregorianConversionError)));