New Unchecked - parsicore/parsidate GitHub Wiki
Constructor (unsafe) ParsiDate::new_unchecked
Creates a new ParsiDate instance from year, month, and day components without performing any validation.
⚠️ Warning: Unsafe Operation ⚠️
This function is marked unsafe because it completely bypasses the validation checks normally performed by the safe ParsiDate::new constructor.
- If you provide invalid components (e.g.,
month = 13,day = 32,day = 30for Esfand in a common year,year = 0,year = 10000), this function will still create aParsiDateinstance containing that invalid data. - Subsequent operations on such an invalid
ParsiDateinstance (like formatting, comparison, arithmetic, or even simple getters if they rely on internal consistency) can lead to unpredictable behavior, incorrect results, logic errors, or runtime panics.
Do not use this function unless you meet the following conditions:
- You have already rigorously validated the
year,month, anddaycomponents through external means before calling this function. - You have an absolute performance requirement that necessitates skipping the validation overhead of
ParsiDate::new.
In nearly all typical use cases, the safe ParsiDate::new constructor is the strongly preferred and recommended choice.
Safety Contract
The caller MUST guarantee that the provided year, month, and day combination:
- Represents a logically valid date within the rules of the Persian (Hejri-Shamsi) calendar. This includes:
monthis between 1 and 12 (inclusive).dayis between 1 and the correct number of days for the givenmonthandyear(considering 31 days for months 1-6, 30 days for months 7-11, and 29 or 30 days for month 12 based on whetheryearis leap).
- The
yearis within the supported range of this library (e.g.,[1, 9999]).
Failure to uphold this guarantee violates the safety contract and invokes undefined behavior from the perspective of this library's date logic, potentially leading to the issues mentioned in the warning above.
Arguments
year(i32or similar integer type): The year component. Must be pre-validated by the caller.month(u8or similar integer type): The month component. Must be pre-validated by the caller.day(u8or similar integer type): The day component. Must be pre-validated by the caller.
Returns
- A
ParsiDateinstance containing the providedyear,month, andday, regardless of whether they form a valid date.
Examples (Rust)
use parsidate::{ParsiDate, DateError}; // Assuming ParsiDate struct and potentially helpers
// --- !!! Incorrect Usage Example !!! ---
// DO NOT DO THIS unless you are 100% certain of validity elsewhere.
// Creating an invalid date (Esfand 30 in a common year 1404)
// let invalid_date = unsafe { ParsiDate::new_unchecked(1404, 12, 30) };
// Even though ParsiDate::new(1404, 12, 30) would return Err,
// new_unchecked creates the object.
// assert!(!invalid_date.is_valid()); // Checking validity later confirms it's bad.
// Using invalid_date further could lead to panics or incorrect results.
// --- Correct Usage Example (with Prior Validation) ---
// Assume these components have been pre-validated by some robust external logic
let p_year = 1403; // A leap year
let p_month = 12; // Esfand
let p_day = 30; // Valid day for Esfand in 1403
// Example of a hypothetical external validation function
// In reality, use a proper date validation library or ParsiDate::new itself
// if performance isn't the absolute bottleneck.
fn is_known_valid(y: i32, m: u8, d: u8) -> bool {
// This is a simplified check; a real one needs ParsiDate::days_in_month logic
// or use the result of ParsiDate::new(y, m, d).is_ok()
const MIN_YEAR: i32 = 1;
const MAX_YEAR: i32 = 9999; // Use the actual library constants if available
if !(MIN_YEAR..=MAX_YEAR).contains(&y) || !(1..=12).contains(&m) || d < 1 {
return false;
}
// A real check needs ParsiDate::days_in_month(y, m)
let max_days = if m <= 6 { 31 } else if m <= 11 { 30 } else {
if ParsiDate::is_persian_leap_year(y) { 30 } else { 29 }
};
d <= max_days
}
// Only call new_unchecked if the validation passed
if is_known_valid(p_year, p_month, p_day) {
println!("Validation passed, proceeding with unsafe construction.");
// It's now considered safe to use new_unchecked because the caller
// has upheld the safety contract.
let date = unsafe { ParsiDate::new_unchecked(p_year, p_month, p_day) };
// Verify the components were stored
assert_eq!(date.year(), 1403);
assert_eq!(date.month(), 12);
assert_eq!(date.day(), 30);
assert!(date.is_valid()); // Should pass if is_known_valid is correct
} else {
// If validation failed, DO NOT call new_unchecked.
eprintln!("Validation failed for year={}, month={}, day={}. Cannot use new_unchecked.", p_year, p_month, p_day);
// Handle the error appropriately (e.g., return Err, panic, log).
// For demonstration, we just print. In real code, you'd likely return an error.
// For instance: return Err(DateError::InvalidDate);
}
// Example with different valid data
let p_year2 = 1404; // Common year
let p_month2 = 7; // Mehr
let p_day2 = 30; // Last day of Mehr
if is_known_valid(p_year2, p_month2, p_day2) {
let date2 = unsafe { ParsiDate::new_unchecked(p_year2, p_month2, p_day2) };
assert_eq!(date2.year(), 1404);
assert_eq!(date2.month(), 7);
assert_eq!(date2.day(), 30);
assert!(date2.is_valid());
} else {
eprintln!("Validation failed for year={}, month={}, day={}.", p_year2, p_month2, p_day2);
}