// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
//! This module contains types and implementations for the Persian calendar.
//!
//! ```rust
//! use icu::calendar::{Date, DateTime};
//!
//! // `Date` type
//! let persian_date = Date::try_new_persian_date(1348, 10, 11)
//! .expect("Failed to initialize Persian Date instance.");
//!
//! // `DateTime` type
//! let persian_datetime =
//! DateTime::try_new_persian_datetime(1348, 10, 11, 13, 1, 0)
//! .expect("Failed to initialize Persian DateTime instance.");
//!
//! // `Date` checks
//! assert_eq!(persian_date.year().number, 1348);
//! assert_eq!(persian_date.month().ordinal, 10);
//! assert_eq!(persian_date.day_of_month().0, 11);
//!
//! // `DateTime` checks
//! assert_eq!(persian_datetime.date.year().number, 1348);
//! assert_eq!(persian_datetime.date.month().ordinal, 10);
//! assert_eq!(persian_datetime.date.day_of_month().0, 11);
//! assert_eq!(persian_datetime.time.hour.number(), 13);
//! assert_eq!(persian_datetime.time.minute.number(), 1);
//! assert_eq!(persian_datetime.time.second.number(), 0);
//! ```
use crate ::any_calendar::AnyCalendarKind;
use crate ::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic};
use crate ::iso::Iso;
use crate ::{types, Calendar, CalendarError, Date, DateDuration, DateDurationUnit, DateT
ime, Time};
use ::tinystr::tinystr;
use calendrical_calculations::helpers::I32CastError;
use calendrical_calculations::rata_die::RataDie;
/// The Persian Calendar
///
/// The [Persian Calendar] is a solar calendar used officially by the countries of Iran and Afghanistan and many Persian-speaking regions.
/// It has 12 months and other similarities to the Gregorian Calendar
///
/// This type can be used with [`Date`] or [`DateTime`] to represent dates in this calendar.
///
/// [Persian Calendar]: https://en.wikipedia.org/wiki/Solar_Hijri_calendar
///
/// # Era codes
///
/// This calendar supports only one era code, which starts from the year of the Hijra, designated as "ah".
///
/// # Month codes
///
/// This calendar supports 12 solar month codes (`"M01" - "M12"`)
#[ derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[ allow(clippy::exhaustive_structs)]
pub struct Persian;
#[ derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
/// The inner date type used for representing [`Date`]s of [`Persian`]. See [`Date`] and [`Persian`] for more details.
pub struct PersianDateInner(ArithmeticDate<Persian>);
impl CalendarArithmetic for Persian {
type YearInfo = ();
fn month_days(year: i32, month: u8, _data: ()) -> u8 {
match month {
1 ..=6 => 31 ,
7 ..=11 => 30 ,
12 if Self ::is_leap_year(year, ()) => 30 ,
12 => 29 ,
_ => 0 ,
}
}
fn months_for_every_year(_: i32, _data: ()) -> u8 {
12
}
fn is_leap_year(p_year: i32, _data: ()) -> bool {
calendrical_calculations::persian::is_leap_year(p_year, _data)
}
fn days_in_provided_year(year: i32, _data: ()) -> u16 {
if Self ::is_leap_year(year, ()) {
366
} else {
365
}
}
fn last_month_day_in_year(year: i32, _data: ()) -> (u8, u8) {
if Self ::is_leap_year(year, ()) {
(12 , 30 )
} else {
(12 , 29 )
}
}
}
impl Calendar for Persian {
type DateInner = PersianDateInner;
fn date_from_codes(
&self ,
era: types::Era,
year: i32,
month_code: types::MonthCode,
day: u8,
) -> Result<Self ::DateInner, CalendarError> {
let year = if era.0 == tinystr!(16 , "ah" ) || era.0 == tinystr!(16 , "persian" ) {
year
} else {
return Err(CalendarError::UnknownEra(era.0 , self .debug_name()));
};
ArithmeticDate::new_from_codes(self , year, month_code, day).map(PersianDateInner)
}
fn date_from_iso(&self , iso: Date<Iso>) -> PersianDateInner {
let fixed_iso = Iso::fixed_from_iso(*iso.inner());
Self ::fast_persian_from_fixed(fixed_iso)
}
fn date_to_iso(&self , date: &Self ::DateInner) -> Date<Iso> {
let fixed_persian = Persian::fixed_from_fast_persian(*date);
Iso::iso_from_fixed(fixed_persian)
}
fn months_in_year(&self , date: &Self ::DateInner) -> u8 {
date.0 .months_in_year()
}
fn days_in_year(&self , date: &Self ::DateInner) -> u16 {
date.0 .days_in_year()
}
fn days_in_month(&self , date: &Self ::DateInner) -> u8 {
date.0 .days_in_month()
}
fn day_of_week(&self , date: &Self ::DateInner) -> types::IsoWeekday {
Iso.day_of_week(self .date_to_iso(date).inner())
}
fn offset_date(&self , date: &mut Self ::DateInner, offset: DateDuration<Self >) {
date.0 .offset_date(offset, &())
}
#[ allow(clippy::field_reassign_with_default)]
fn until(
&self ,
date1: &Self ::DateInner,
date2: &Self ::DateInner,
_calendar2: &Self ,
_largest_unit: DateDurationUnit,
_smallest_unit: DateDurationUnit,
) -> DateDuration<Self > {
date1.0 .until(date2.0 , _largest_unit, _smallest_unit)
}
fn year(&self , date: &Self ::DateInner) -> types::FormattableYear {
Self ::year_as_persian(date.0 .year)
}
fn is_in_leap_year(&self , date: &Self ::DateInner) -> bool {
Self ::is_leap_year(date.0 .year, ())
}
fn month(&self , date: &Self ::DateInner) -> types::FormattableMonth {
date.0 .month()
}
fn day_of_month(&self , date: &Self ::DateInner) -> types::DayOfMonth {
date.0 .day_of_month()
}
fn day_of_year_info(&self , date: &Self ::DateInner) -> types::DayOfYearInfo {
let prev_year = date.0 .year.saturating_sub(1 );
let next_year = date.0 .year.saturating_add(1 );
types::DayOfYearInfo {
day_of_year: date.0 .day_of_year(),
days_in_year: date.0 .days_in_year(),
prev_year: Persian::year_as_persian(prev_year),
days_in_prev_year: Persian::days_in_provided_year(prev_year, ()),
next_year: Persian::year_as_persian(next_year),
}
}
fn debug_name(&self ) -> &'static str {
"Persian"
}
// Missing any_calendar persian tests, the rest is completed
fn any_calendar_kind(&self ) -> Option<AnyCalendarKind> {
Some(AnyCalendarKind::Persian)
}
}
impl Persian {
/// Constructs a new Persian Calendar
pub fn new() -> Self {
Self
}
fn fixed_from_fast_persian(p_date: PersianDateInner) -> RataDie {
calendrical_calculations::persian::fixed_from_fast_persian(
p_date.0 .year,
p_date.0 .month,
p_date.0 .day,
)
}
fn fast_persian_from_fixed(date: RataDie) -> PersianDateInner {
let (year, month, day) =
match calendrical_calculations::persian::fast_persian_from_fixed(date) {
Err(I32CastError::BelowMin) => return PersianDateInner(ArithmeticDate::min_date()),
Err(I32CastError::AboveMax) => return PersianDateInner(ArithmeticDate::max_date()),
Ok(ymd) => ymd,
};
PersianDateInner(ArithmeticDate::new_unchecked(year, month, day))
}
fn year_as_persian(year: i32) -> types::FormattableYear {
types::FormattableYear {
era: types::Era(tinystr!(16 , "ah" )),
number: year,
cyclic: None,
related_iso: None,
}
}
}
impl Date<Persian> {
/// Construct new Persian Date.
///
/// Has no negative years, only era is the AH/AP.
///
/// ```rust
/// use icu::calendar::Date;
///
/// let date_persian = Date::try_new_persian_date(1392, 4, 25)
/// .expect("Failed to initialize Persian Date instance.");
///
/// assert_eq!(date_persian.year().number, 1392);
/// assert_eq!(date_persian.month().ordinal, 4);
/// assert_eq!(date_persian.day_of_month().0, 25);
/// ```
pub fn try_new_persian_date(
year: i32,
month: u8,
day: u8,
) -> Result<Date<Persian>, CalendarError> {
ArithmeticDate::new_from_ordinals(year, month, day)
.map(PersianDateInner)
.map(|inner| Date::from_raw(inner, Persian))
}
}
impl DateTime<Persian> {
/// Construct a new Persian datetime from integers.
///
/// ```rust
/// use icu::calendar::DateTime;
///
/// let datetime_persian =
/// DateTime::try_new_persian_datetime(474, 10, 11, 13, 1, 0)
/// .expect("Failed to initialize Persian DateTime instance.");
///
/// assert_eq!(datetime_persian.date.year().number, 474);
/// assert_eq!(datetime_persian.date.month().ordinal, 10);
/// assert_eq!(datetime_persian.date.day_of_month().0, 11);
/// assert_eq!(datetime_persian.time.hour.number(), 13);
/// assert_eq!(datetime_persian.time.minute.number(), 1);
/// assert_eq!(datetime_persian.time.second.number(), 0);
/// ```
pub fn try_new_persian_datetime(
year: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
) -> Result<DateTime<Persian>, CalendarError> {
Ok(DateTime {
date: Date::try_new_persian_date(year, month, day)?,
time: Time::try_new(hour, minute, second, 0 )?,
})
}
}
#[ cfg(test)]
mod tests {
use super ::*;
#[ derive(Debug)]
struct DateCase {
year: i32,
month: u8,
day: u8,
}
static TEST_FIXED_DATE: [i64; 21 ] = [
656786 , 664224 , 671401 , 694799 , 702806 , 704424 , 708842 , 709409 , 709580 , 727274 , 728714 ,
739330 , 739331 , 744313 , 763436 , 763437 , 764652 , 775123 , 775488 , 775489 , 1317874 ,
];
// Test data are provided for the range 1178-3000 AP, for which
// we know the 33-year rule, with the override table, matches the
// astronomical calculations based on the 52.5 degrees east meridian.
static CASES: [DateCase; 21 ] = [
// First year for which 33-year rule matches the astronomical calculation
DateCase {
year: 1178 ,
month: 1 ,
day: 1 ,
},
DateCase {
year: 1198 ,
month: 5 ,
day: 10 ,
},
DateCase {
year: 1218 ,
month: 1 ,
day: 7 ,
},
DateCase {
year: 1282 ,
month: 1 ,
day: 29 ,
},
// The beginning of the year the calendar was adopted
DateCase {
year: 1304 ,
month: 1 ,
day: 1 ,
},
DateCase {
year: 1308 ,
month: 6 ,
day: 3 ,
},
DateCase {
year: 1320 ,
month: 7 ,
day: 7 ,
},
DateCase {
year: 1322 ,
month: 1 ,
day: 29 ,
},
DateCase {
year: 1322 ,
month: 7 ,
day: 14 ,
},
DateCase {
year: 1370 ,
month: 12 ,
day: 27 ,
},
DateCase {
year: 1374 ,
month: 12 ,
day: 6 ,
},
// First day that the 2820-year rule fails
DateCase {
year: 1403 ,
month: 12 ,
day: 30 ,
},
// First Nowruz that the 2820-year rule fails
DateCase {
year: 1404 ,
month: 1 ,
day: 1 ,
},
DateCase {
year: 1417 ,
month: 8 ,
day: 19 ,
},
// First day the unmodified astronomical algorithm fails
DateCase {
year: 1469 ,
month: 12 ,
day: 30 ,
},
// First Nowruz the unmodified astronomical algorithm fails
DateCase {
year: 1470 ,
month: 1 ,
day: 1 ,
},
DateCase {
year: 1473 ,
month: 4 ,
day: 28 ,
},
// Last year the 33-year rule matches the modified astronomical calculation
DateCase {
year: 1501 ,
month: 12 ,
day: 29 ,
},
DateCase {
year: 1502 ,
month: 12 ,
day: 29 ,
},
DateCase {
year: 1503 ,
month: 1 ,
day: 1 ,
},
DateCase {
year: 2988 ,
month: 1 ,
day: 1 ,
},
];
fn days_in_provided_year_core(year: i32) -> u16 {
let fixed_year =
calendrical_calculations::persian::fixed_from_fast_persian(year, 1 , 1 ).to_i64_date();
let next_fixed_year =
calendrical_calculations::persian::fixed_from_fast_persian(year + 1 , 1 , 1 )
.to_i64_date();
(next_fixed_year - fixed_year) as u16
}
#[ test]
fn test_persian_leap_year() {
let mut leap_years: [i32; 21 ] = [0 ; 21 ];
// These values were computed from the "Calendrical Calculations" reference code output
let expected_values = [
false , false , true , false , true , false , false , false , false , true , false , true , false ,
false , true , false , false , false , false , true , true ,
];
for (index, case) in CASES.iter().enumerate() {
leap_years[index] = case.year;
}
for (year, bool) in leap_years.iter().zip(expected_values.iter()) {
assert_eq!(Persian::is_leap_year(*year, ()), *bool);
}
}
#[ test]
fn days_in_provided_year_test() {
for case in CASES.iter() {
assert_eq!(
days_in_provided_year_core(case.year),
Persian::days_in_provided_year(case.year, ())
);
}
}
#[ test]
fn test_fixed_from_persian() {
for (case, f_date) in CASES.iter().zip(TEST_FIXED_DATE.iter()) {
let date = Date::try_new_persian_date(case.year, case.month, case.day).unwrap();
assert_eq!(
Persian::fixed_from_fast_persian(*date.inner()).to_i64_date(),
*f_date,
"{case:?}"
);
}
}
#[ test]
fn test_persian_from_fixed() {
for (case, f_date) in CASES.iter().zip(TEST_FIXED_DATE.iter()) {
let date = Date::try_new_persian_date(case.year, case.month, case.day).unwrap();
assert_eq!(
Persian::fast_persian_from_fixed(RataDie::new(*f_date)),
date.inner,
"{case:?}"
);
}
}
#[ test]
fn test_day_of_year_info() {
#[ derive(Debug)]
struct TestCase {
input: i32,
expected_prev: i32,
expected_next: i32,
}
let test_cases = [
TestCase {
input: 0 ,
expected_prev: -1 ,
expected_next: 1 ,
},
TestCase {
input: i32::MAX,
expected_prev: i32::MAX - 1 ,
expected_next: i32::MAX, // can't go above i32::MAX
},
TestCase {
input: i32::MIN + 1 ,
expected_prev: i32::MIN,
expected_next: i32::MIN + 2 ,
},
TestCase {
input: i32::MIN,
expected_prev: i32::MIN, // can't go below i32::MIN
expected_next: i32::MIN + 1 ,
},
];
for case in test_cases {
let date = Date::try_new_persian_date(case.input, 1 , 1 ).unwrap();
let info = Persian::day_of_year_info(&Persian, date.inner());
assert_eq!(info.prev_year.number, case.expected_prev, "{:?}" , case);
assert_eq!(info.next_year.number, case.expected_next, "{:?}" , case);
}
}
// From https://calendar.ut.ac.ir/Fa/News/Data/Doc/KabiseShamsi1206-1498-new.pdf
// Plain text version at https://github.com/roozbehp/persiancalendar/blob/main/kabise.txt
static CALENDAR_UT_AC_IR_TEST_DATA: [(i32, bool, i32, u32, u32); 293 ] = [
(1206 , false , 1827 , 3 , 22 ),
(1207 , false , 1828 , 3 , 21 ),
(1208 , false , 1829 , 3 , 21 ),
(1209 , false , 1830 , 3 , 21 ),
(1210 , true , 1831 , 3 , 21 ),
(1211 , false , 1832 , 3 , 21 ),
(1212 , false , 1833 , 3 , 21 ),
(1213 , false , 1834 , 3 , 21 ),
(1214 , true , 1835 , 3 , 21 ),
(1215 , false , 1836 , 3 , 21 ),
(1216 , false , 1837 , 3 , 21 ),
(1217 , false , 1838 , 3 , 21 ),
(1218 , true , 1839 , 3 , 21 ),
(1219 , false , 1840 , 3 , 21 ),
(1220 , false , 1841 , 3 , 21 ),
(1221 , false , 1842 , 3 , 21 ),
(1222 , true , 1843 , 3 , 21 ),
(1223 , false , 1844 , 3 , 21 ),
(1224 , false , 1845 , 3 , 21 ),
(1225 , false , 1846 , 3 , 21 ),
(1226 , true , 1847 , 3 , 21 ),
(1227 , false , 1848 , 3 , 21 ),
(1228 , false , 1849 , 3 , 21 ),
(1229 , false , 1850 , 3 , 21 ),
(1230 , true , 1851 , 3 , 21 ),
(1231 , false , 1852 , 3 , 21 ),
(1232 , false , 1853 , 3 , 21 ),
(1233 , false , 1854 , 3 , 21 ),
(1234 , true , 1855 , 3 , 21 ),
(1235 , false , 1856 , 3 , 21 ),
(1236 , false , 1857 , 3 , 21 ),
(1237 , false , 1858 , 3 , 21 ),
(1238 , true , 1859 , 3 , 21 ),
(1239 , false , 1860 , 3 , 21 ),
(1240 , false , 1861 , 3 , 21 ),
(1241 , false , 1862 , 3 , 21 ),
(1242 , false , 1863 , 3 , 21 ),
(1243 , true , 1864 , 3 , 20 ),
(1244 , false , 1865 , 3 , 21 ),
(1245 , false , 1866 , 3 , 21 ),
(1246 , false , 1867 , 3 , 21 ),
(1247 , true , 1868 , 3 , 20 ),
(1248 , false , 1869 , 3 , 21 ),
(1249 , false , 1870 , 3 , 21 ),
(1250 , false , 1871 , 3 , 21 ),
(1251 , true , 1872 , 3 , 20 ),
(1252 , false , 1873 , 3 , 21 ),
(1253 , false , 1874 , 3 , 21 ),
(1254 , false , 1875 , 3 , 21 ),
(1255 , true , 1876 , 3 , 20 ),
(1256 , false , 1877 , 3 , 21 ),
(1257 , false , 1878 , 3 , 21 ),
(1258 , false , 1879 , 3 , 21 ),
(1259 , true , 1880 , 3 , 20 ),
(1260 , false , 1881 , 3 , 21 ),
(1261 , false , 1882 , 3 , 21 ),
(1262 , false , 1883 , 3 , 21 ),
(1263 , true , 1884 , 3 , 20 ),
(1264 , false , 1885 , 3 , 21 ),
(1265 , false , 1886 , 3 , 21 ),
(1266 , false , 1887 , 3 , 21 ),
(1267 , true , 1888 , 3 , 20 ),
(1268 , false , 1889 , 3 , 21 ),
(1269 , false , 1890 , 3 , 21 ),
(1270 , false , 1891 , 3 , 21 ),
(1271 , true , 1892 , 3 , 20 ),
(1272 , false , 1893 , 3 , 21 ),
(1273 , false , 1894 , 3 , 21 ),
(1274 , false , 1895 , 3 , 21 ),
(1275 , false , 1896 , 3 , 20 ),
(1276 , true , 1897 , 3 , 20 ),
(1277 , false , 1898 , 3 , 21 ),
(1278 , false , 1899 , 3 , 21 ),
(1279 , false , 1900 , 3 , 21 ),
(1280 , true , 1901 , 3 , 21 ),
(1281 , false , 1902 , 3 , 22 ),
(1282 , false , 1903 , 3 , 22 ),
(1283 , false , 1904 , 3 , 21 ),
(1284 , true , 1905 , 3 , 21 ),
(1285 , false , 1906 , 3 , 22 ),
(1286 , false , 1907 , 3 , 22 ),
(1287 , false , 1908 , 3 , 21 ),
(1288 , true , 1909 , 3 , 21 ),
(1289 , false , 1910 , 3 , 22 ),
(1290 , false , 1911 , 3 , 22 ),
(1291 , false , 1912 , 3 , 21 ),
(1292 , true , 1913 , 3 , 21 ),
(1293 , false , 1914 , 3 , 22 ),
(1294 , false , 1915 , 3 , 22 ),
(1295 , false , 1916 , 3 , 21 ),
(1296 , true , 1917 , 3 , 21 ),
(1297 , false , 1918 , 3 , 22 ),
(1298 , false , 1919 , 3 , 22 ),
(1299 , false , 1920 , 3 , 21 ),
(1300 , true , 1921 , 3 , 21 ),
(1301 , false , 1922 , 3 , 22 ),
(1302 , false , 1923 , 3 , 22 ),
(1303 , false , 1924 , 3 , 21 ),
(1304 , true , 1925 , 3 , 21 ),
(1305 , false , 1926 , 3 , 22 ),
(1306 , false , 1927 , 3 , 22 ),
(1307 , false , 1928 , 3 , 21 ),
(1308 , false , 1929 , 3 , 21 ),
(1309 , true , 1930 , 3 , 21 ),
(1310 , false , 1931 , 3 , 22 ),
(1311 , false , 1932 , 3 , 21 ),
(1312 , false , 1933 , 3 , 21 ),
(1313 , true , 1934 , 3 , 21 ),
(1314 , false , 1935 , 3 , 22 ),
(1315 , false , 1936 , 3 , 21 ),
(1316 , false , 1937 , 3 , 21 ),
(1317 , true , 1938 , 3 , 21 ),
(1318 , false , 1939 , 3 , 22 ),
(1319 , false , 1940 , 3 , 21 ),
(1320 , false , 1941 , 3 , 21 ),
(1321 , true , 1942 , 3 , 21 ),
(1322 , false , 1943 , 3 , 22 ),
(1323 , false , 1944 , 3 , 21 ),
(1324 , false , 1945 , 3 , 21 ),
(1325 , true , 1946 , 3 , 21 ),
(1326 , false , 1947 , 3 , 22 ),
(1327 , false , 1948 , 3 , 21 ),
(1328 , false , 1949 , 3 , 21 ),
(1329 , true , 1950 , 3 , 21 ),
(1330 , false , 1951 , 3 , 22 ),
(1331 , false , 1952 , 3 , 21 ),
(1332 , false , 1953 , 3 , 21 ),
(1333 , true , 1954 , 3 , 21 ),
(1334 , false , 1955 , 3 , 22 ),
(1335 , false , 1956 , 3 , 21 ),
(1336 , false , 1957 , 3 , 21 ),
(1337 , true , 1958 , 3 , 21 ),
(1338 , false , 1959 , 3 , 22 ),
(1339 , false , 1960 , 3 , 21 ),
(1340 , false , 1961 , 3 , 21 ),
(1341 , false , 1962 , 3 , 21 ),
(1342 , true , 1963 , 3 , 21 ),
(1343 , false , 1964 , 3 , 21 ),
(1344 , false , 1965 , 3 , 21 ),
(1345 , false , 1966 , 3 , 21 ),
(1346 , true , 1967 , 3 , 21 ),
(1347 , false , 1968 , 3 , 21 ),
(1348 , false , 1969 , 3 , 21 ),
(1349 , false , 1970 , 3 , 21 ),
(1350 , true , 1971 , 3 , 21 ),
(1351 , false , 1972 , 3 , 21 ),
(1352 , false , 1973 , 3 , 21 ),
(1353 , false , 1974 , 3 , 21 ),
(1354 , true , 1975 , 3 , 21 ),
(1355 , false , 1976 , 3 , 21 ),
(1356 , false , 1977 , 3 , 21 ),
(1357 , false , 1978 , 3 , 21 ),
(1358 , true , 1979 , 3 , 21 ),
(1359 , false , 1980 , 3 , 21 ),
(1360 , false , 1981 , 3 , 21 ),
(1361 , false , 1982 , 3 , 21 ),
(1362 , true , 1983 , 3 , 21 ),
(1363 , false , 1984 , 3 , 21 ),
(1364 , false , 1985 , 3 , 21 ),
(1365 , false , 1986 , 3 , 21 ),
(1366 , true , 1987 , 3 , 21 ),
(1367 , false , 1988 , 3 , 21 ),
(1368 , false , 1989 , 3 , 21 ),
(1369 , false , 1990 , 3 , 21 ),
(1370 , true , 1991 , 3 , 21 ),
(1371 , false , 1992 , 3 , 21 ),
(1372 , false , 1993 , 3 , 21 ),
(1373 , false , 1994 , 3 , 21 ),
(1374 , false , 1995 , 3 , 21 ),
(1375 , true , 1996 , 3 , 20 ),
(1376 , false , 1997 , 3 , 21 ),
(1377 , false , 1998 , 3 , 21 ),
(1378 , false , 1999 , 3 , 21 ),
(1379 , true , 2000 , 3 , 20 ),
(1380 , false , 2001 , 3 , 21 ),
(1381 , false , 2002 , 3 , 21 ),
(1382 , false , 2003 , 3 , 21 ),
(1383 , true , 2004 , 3 , 20 ),
(1384 , false , 2005 , 3 , 21 ),
(1385 , false , 2006 , 3 , 21 ),
(1386 , false , 2007 , 3 , 21 ),
(1387 , true , 2008 , 3 , 20 ),
(1388 , false , 2009 , 3 , 21 ),
(1389 , false , 2010 , 3 , 21 ),
(1390 , false , 2011 , 3 , 21 ),
(1391 , true , 2012 , 3 , 20 ),
(1392 , false , 2013 , 3 , 21 ),
(1393 , false , 2014 , 3 , 21 ),
(1394 , false , 2015 , 3 , 21 ),
(1395 , true , 2016 , 3 , 20 ),
(1396 , false , 2017 , 3 , 21 ),
(1397 , false , 2018 , 3 , 21 ),
(1398 , false , 2019 , 3 , 21 ),
(1399 , true , 2020 , 3 , 20 ),
(1400 , false , 2021 , 3 , 21 ),
(1401 , false , 2022 , 3 , 21 ),
(1402 , false , 2023 , 3 , 21 ),
(1403 , true , 2024 , 3 , 20 ),
(1404 , false , 2025 , 3 , 21 ),
(1405 , false , 2026 , 3 , 21 ),
(1406 , false , 2027 , 3 , 21 ),
(1407 , false , 2028 , 3 , 20 ),
(1408 , true , 2029 , 3 , 20 ),
(1409 , false , 2030 , 3 , 21 ),
(1410 , false , 2031 , 3 , 21 ),
(1411 , false , 2032 , 3 , 20 ),
(1412 , true , 2033 , 3 , 20 ),
(1413 , false , 2034 , 3 , 21 ),
(1414 , false , 2035 , 3 , 21 ),
(1415 , false , 2036 , 3 , 20 ),
(1416 , true , 2037 , 3 , 20 ),
(1417 , false , 2038 , 3 , 21 ),
(1418 , false , 2039 , 3 , 21 ),
(1419 , false , 2040 , 3 , 20 ),
(1420 , true , 2041 , 3 , 20 ),
(1421 , false , 2042 , 3 , 21 ),
(1422 , false , 2043 , 3 , 21 ),
(1423 , false , 2044 , 3 , 20 ),
(1424 , true , 2045 , 3 , 20 ),
(1425 , false , 2046 , 3 , 21 ),
(1426 , false , 2047 , 3 , 21 ),
(1427 , false , 2048 , 3 , 20 ),
(1428 , true , 2049 , 3 , 20 ),
(1429 , false , 2050 , 3 , 21 ),
(1430 , false , 2051 , 3 , 21 ),
(1431 , false , 2052 , 3 , 20 ),
(1432 , true , 2053 , 3 , 20 ),
(1433 , false , 2054 , 3 , 21 ),
(1434 , false , 2055 , 3 , 21 ),
(1435 , false , 2056 , 3 , 20 ),
(1436 , true , 2057 , 3 , 20 ),
(1437 , false , 2058 , 3 , 21 ),
(1438 , false , 2059 , 3 , 21 ),
(1439 , false , 2060 , 3 , 20 ),
(1440 , false , 2061 , 3 , 20 ),
(1441 , true , 2062 , 3 , 20 ),
(1442 , false , 2063 , 3 , 21 ),
(1443 , false , 2064 , 3 , 20 ),
(1444 , false , 2065 , 3 , 20 ),
(1445 , true , 2066 , 3 , 20 ),
(1446 , false , 2067 , 3 , 21 ),
(1447 , false , 2068 , 3 , 20 ),
(1448 , false , 2069 , 3 , 20 ),
(1449 , true , 2070 , 3 , 20 ),
(1450 , false , 2071 , 3 , 21 ),
(1451 , false , 2072 , 3 , 20 ),
(1452 , false , 2073 , 3 , 20 ),
(1453 , true , 2074 , 3 , 20 ),
(1454 , false , 2075 , 3 , 21 ),
(1455 , false , 2076 , 3 , 20 ),
(1456 , false , 2077 , 3 , 20 ),
(1457 , true , 2078 , 3 , 20 ),
(1458 , false , 2079 , 3 , 21 ),
(1459 , false , 2080 , 3 , 20 ),
(1460 , false , 2081 , 3 , 20 ),
(1461 , true , 2082 , 3 , 20 ),
(1462 , false , 2083 , 3 , 21 ),
(1463 , false , 2084 , 3 , 20 ),
(1464 , false , 2085 , 3 , 20 ),
(1465 , true , 2086 , 3 , 20 ),
(1466 , false , 2087 , 3 , 21 ),
(1467 , false , 2088 , 3 , 20 ),
(1468 , false , 2089 , 3 , 20 ),
(1469 , true , 2090 , 3 , 20 ),
(1470 , false , 2091 , 3 , 21 ),
(1471 , false , 2092 , 3 , 20 ),
(1472 , false , 2093 , 3 , 20 ),
(1473 , false , 2094 , 3 , 20 ),
(1474 , true , 2095 , 3 , 20 ),
(1475 , false , 2096 , 3 , 20 ),
(1476 , false , 2097 , 3 , 20 ),
(1477 , false , 2098 , 3 , 20 ),
(1478 , true , 2099 , 3 , 20 ),
(1479 , false , 2100 , 3 , 21 ),
(1480 , false , 2101 , 3 , 21 ),
(1481 , false , 2102 , 3 , 21 ),
(1482 , true , 2103 , 3 , 21 ),
(1483 , false , 2104 , 3 , 21 ),
(1484 , false , 2105 , 3 , 21 ),
(1485 , false , 2106 , 3 , 21 ),
(1486 , true , 2107 , 3 , 21 ),
(1487 , false , 2108 , 3 , 21 ),
(1488 , false , 2109 , 3 , 21 ),
(1489 , false , 2110 , 3 , 21 ),
(1490 , true , 2111 , 3 , 21 ),
(1491 , false , 2112 , 3 , 21 ),
(1492 , false , 2113 , 3 , 21 ),
(1493 , false , 2114 , 3 , 21 ),
(1494 , true , 2115 , 3 , 21 ),
(1495 , false , 2116 , 3 , 21 ),
(1496 , false , 2117 , 3 , 21 ),
(1497 , false , 2118 , 3 , 21 ),
(1498 , true , 2119 , 3 , 21 ),
];
#[ test]
fn test_calendar_ut_ac_ir_data() {
for (p_year, leap, iso_year, iso_month, iso_day) in CALENDAR_UT_AC_IR_TEST_DATA.iter() {
assert_eq!(Persian::is_leap_year(*p_year, ()), *leap);
let persian_date = Date::try_new_persian_date(*p_year, 1 , 1 ).unwrap();
let iso_date = persian_date.to_calendar(Iso);
assert_eq!(iso_date.year().number, *iso_year);
assert_eq!(iso_date.month().ordinal, *iso_month);
assert_eq!(iso_date.day_of_month().0 , *iso_day);
}
}
}
Messung V0.5 in Prozent C=89 H=100 G=94
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland