From Ordinal - jalalvandi/ParsiDate GitHub Wiki
from_ordinal
Static Method Creates a ParsiDate
instance from a given Persian year and the ordinal day number within that year.
Description
This static method reconstructs a specific ParsiDate
(year, month, day) based on the provided Persian year
and the ordinal
day count. The ordinal day represents the position of the day within the year, starting from 1 for Farvardin 1st, 2 for Farvardin 2nd, up to 365 for the last day of a common year or 366 for the last day of a leap year.
The method calculates the corresponding month and day by iteratively subtracting the lengths of the months from the ordinal value until the correct month and day are determined. It correctly accounts for the lengths of Persian months (31 days for months 1-6, 30 days for months 7-11) and the length of Esfand (month 12), which is 30 days in a leap year and 29 days in a common year.
The validity of the ordinal
value is checked against the actual number of days in the provided year
. The validity of the year
itself is also implicitly checked during the final construction of the ParsiDate
.
Arguments
year
: The Persian year (e.g.,1403
) as an integer type (e.g.,i32
). Must be within the range supported byParsiDate
(typically 1 to 9999).ordinal
: The day number within the specifiedyear
(e.g.,1
,100
,365
,366
) as an integer type (e.g.,u32
). Must be between 1 and the total number of days in the givenyear
(inclusive).
Returns
Ok(ParsiDate)
: If theyear
is valid and theordinal
day number is valid for that year, returns the correspondingParsiDate
(with calculated month and day) wrapped inOk
.Err(DateError::InvalidOrdinal)
: If theordinal
value is less than 1 or greater than the total number of days in the specifiedyear
(365 or 366).Err(DateError::InvalidDate)
: If the providedyear
is outside the valid range (e.g., 0 or 10000+). This error might be returned by the final internal validation when attempting to create theParsiDate
instance.
Examples (Rust)
use parsidate::{ParsiDate, DateError}; // Assuming these types exist
// --- Successful Conversions ---
// First day of the year (ordinal 1)
assert_eq!(ParsiDate::from_ordinal(1403, 1), Ok(ParsiDate::new(1403, 1, 1).unwrap()));
// Day 32 (should be Ordibehesht 1st)
// Farvardin has 31 days. 32 - 31 = 1.
assert_eq!(ParsiDate::from_ordinal(1403, 32), Ok(ParsiDate::new(1403, 2, 1).unwrap()));
// A day mid-year (day 100)
// Month lengths: 31, 31, 31 (sum=93). 100 - 93 = 7. Day 100 is 7th of month 4 (Tir).
assert_eq!(ParsiDate::from_ordinal(1403, 100), Ok(ParsiDate::new(1403, 4, 7).unwrap()));
// Last day of a leap year (1403 is leap, 366 days)
assert_eq!(ParsiDate::from_ordinal(1403, 366), Ok(ParsiDate::new(1403, 12, 30).unwrap()));
// Last day of a common year (1404 is common, 365 days)
assert_eq!(ParsiDate::from_ordinal(1404, 365), Ok(ParsiDate::new(1404, 12, 29).unwrap()));
// --- Error Cases ---
// Error: Ordinal is zero (minimum is 1)
assert_eq!(ParsiDate::from_ordinal(1403, 0), Err(DateError::InvalidOrdinal));
// Error: Ordinal too large for a common year (1404 has 365 days)
assert_eq!(ParsiDate::from_ordinal(1404, 366), Err(DateError::InvalidOrdinal));
// Error: Ordinal too large for a leap year (1403 has 366 days)
assert_eq!(ParsiDate::from_ordinal(1403, 367), Err(DateError::InvalidOrdinal));
// Error: Invalid year (e.g., year 0)
// This might trigger InvalidDate during final ParsiDate::new validation
let result_invalid_year = ParsiDate::from_ordinal(0, 100);
assert!(result_invalid_year.is_err());
// The specific error could be InvalidDate or potentially InvalidOrdinal if year check happens first
// assert!(matches!(result_invalid_year, Err(DateError::InvalidDate))); // Example check
// Error: Invalid year (e.g., year 10000)
let result_invalid_year_high = ParsiDate::from_ordinal(10000, 100);
assert!(result_invalid_year_high.is_err());
// assert!(matches!(result_invalid_year_high, Err(DateError::InvalidDate))); // Example check