Sub Duration (ParsiDateTime) - parsicore/parsidate GitHub Wiki
sub_duration
(on ParsiDateTime)
Method Subtracts a chrono::Duration
from this ParsiDateTime
, returning a new ParsiDateTime
.
Description
This method calculates a new ParsiDateTime
by subtracting a specified chrono::Duration
from the current instance. It correctly handles both date and time adjustments, including rollovers across seconds, minutes, hours, and days.
It functions as a convenience method, equivalent to calling add_duration
with the duration
negated (i.e., self.add_duration(-duration)
). The underlying calculation typically involves conversions to/from chrono::NaiveDateTime
to leverage chrono
's robust duration arithmetic.
Arguments
duration
: Thechrono::Duration
to subtract. Note thatDuration
itself can be negative, so subtracting a negative duration is equivalent to adding a positive one.
Returns
Ok(ParsiDateTime)
: If the startingParsiDateTime
is valid, the conversions succeed, and the arithmetic results in a validParsiDateTime
within the supported range, returns the newParsiDateTime
wrapped inOk
.Err(DateError::...)
: Returns an error under the same conditions as theadd_duration
method. This includes:DateError::InvalidDate
/DateError::InvalidTime
: If the startingParsiDateTime
is invalid.DateError::GregorianConversionError
: If intermediate conversions to/from Gregorian fail.DateError::ArithmeticOverflow
: If the resulting date/time falls outside the supported range ofchrono
orParsiDateTime
.
Examples (Rust)
use parsidate::{ParsiDateTime, ParsiDate, DateError};
use chrono::Duration; // Make sure chrono is a dependency
// Example 1: Subtracting seconds that cross midnight backwards
let dt = ParsiDateTime::new(1403, 1, 1, 0, 0, 5).unwrap(); // Farvardin 1st, 5 seconds past midnight
// Subtract 10 seconds
let dt_prev_day_result = dt.sub_duration(Duration::seconds(10));
assert!(dt_prev_day_result.is_ok());
let dt_prev_day = dt_prev_day_result.unwrap();
// Expected: Goes back to the last second of the previous day.
// Previous day: 1402-12-29 (since 1403 is leap, 1402 is common, Esfand has 29 days).
// Time: 00:00:05 - 10s = wraps around to 23:59:55.
assert_eq!(dt_prev_day.date(), ParsiDate::new(1402, 12, 29).unwrap());
assert_eq!(dt_prev_day.time(), (23, 59, 55));
// Example 2: Subtracting hours
let dt2 = ParsiDateTime::new(1403, 5, 10, 2, 15, 0).unwrap(); // Mordad 10th, 02:15:00
// Subtract 4 hours
let dt_minus_4h = dt2.sub_duration(Duration::hours(4));
assert!(dt_minus_4h.is_ok());
let dt_minus_4h_unwrapped = dt_minus_4h.unwrap();
// Expected: Date goes back to Mordad 9th. Time wraps around (02:15 - 4h = -01:45 -> 22:15 prev day)
assert_eq!(dt_minus_4h_unwrapped.date(), ParsiDate::new(1403, 5, 9).unwrap());
assert_eq!(dt_minus_4h_unwrapped.time(), (22, 15, 0));
// Example 3: Error case (potential) - subtracting large duration
let earliest_dt = ParsiDateTime::new(1, 1, 1, 0, 0, 0).unwrap();
let very_long_ago = Duration::days(500 * 365); // Approx 500 years
let result = earliest_dt.sub_duration(very_long_ago);
// This will likely fail due to going before the supported epoch
assert!(result.is_err());
// assert!(matches!(result, Err(DateError::GregorianConversionError) | Err(DateError::ArithmeticOverflow)));