Is Persian Leap Year - jalalvandi/ParsiDate GitHub Wiki

Static Method is_persian_leap_year

Determines whether a given Persian (Solar Hijri / Jalali) year is a leap year, based on a widely used algorithmic approximation.

Description

This static method checks if the provided Persian year is considered a leap year. Because the official Persian calendar leap year determination is based on astronomical observation (the precise timing of the vernal equinox), a purely algorithmic approach is often used for computational purposes.

This function implements a common and highly accurate algorithmic approximation based on a 33-year cycle. According to this algorithm, a Persian year is designated as a leap year if the remainder of year divided by 33 is one of the following specific values:

1, 5, 9, 13, 17, 22, 26, 30

Years less than 1 are explicitly considered non-leap by this function.

Note: While this 33-year cycle algorithm provides excellent accuracy for most historical and near-future dates, it remains an approximation of the true astronomical rule. Discrepancies could potentially arise for years very far in the past or future compared to dates calculated strictly based on vernal equinox timing.

Arguments

  • year: The Persian calendar year (e.g., 1399, 1403) as an integer type (e.g., i32) to be checked.

Returns

  • true if the specified year is determined to be a leap year according to the 33-year cycle algorithm (i.e., year % 33 is in the set {1, 5, 9, 13, 17, 22, 26, 30}).
  • false otherwise (including cases where year < 1).

Note: This method performs a calculation based on the described algorithm and does not typically return errors.

Examples (Rust)

use parsidate::ParsiDate; // Assuming ParsiDate provides this static method

// --- Leap Year Cases (Remainder is in {1, 5, 9, 13, 17, 22, 26, 30}) ---

// 1399 % 33 = 30. Remainder 30 IS in the set -> Leap
assert!(ParsiDate::is_persian_leap_year(1399));

// 1403 % 33 = 17. Remainder 17 IS in the set -> Leap
assert!(ParsiDate::is_persian_leap_year(1403));

// 1408 % 33 = 22. Remainder 22 IS in the set -> Leap
assert!(ParsiDate::is_persian_leap_year(1408));

// Check other leap remainders (e.g., 1, 5, 9...)
assert!(ParsiDate::is_persian_leap_year(1387)); // 1387 % 33 = 1 -> Leap
assert!(ParsiDate::is_persian_leap_year(1391)); // 1391 % 33 = 5 -> Leap
assert!(ParsiDate::is_persian_leap_year(1395)); // 1395 % 33 = 9 -> Leap


// --- Common Year Cases (Remainder is NOT in the set) ---

// 1400 % 33 = 14. Remainder 14 is NOT in the set -> Common
assert!(!ParsiDate::is_persian_leap_year(1400));

// 1404 % 33 = 18. Remainder 18 is NOT in the set -> Common
assert!(!ParsiDate::is_persian_leap_year(1404));

// Check other common remainders
assert!(!ParsiDate::is_persian_leap_year(1401)); // 1401 % 33 = 15 -> Common
assert!(!ParsiDate::is_persian_leap_year(1402)); // 1402 % 33 = 16 -> Common


// --- Edge Cases (Years < 1) ---

// Year 0 is not considered leap
assert!(!ParsiDate::is_persian_leap_year(0));

// Negative years are not considered leap
assert!(!ParsiDate::is_persian_leap_year(-5));
assert!(!ParsiDate::is_persian_leap_year(-33));