PersianDate: A Complete Guide to the Persian Calendar

Converting Gregorian to PersianDate: Methods & CodeConverting Gregorian dates to the Persian (Solar Hijri) calendar is a common need for applications serving Persian-speaking users or dealing with Iranian, Afghan, or regional date formats. This article explains the background of the Persian calendar, outlines several conversion methods (algorithmic, library-based, and server-side), and provides practical code examples in JavaScript, Python, and C#. You’ll also find advice on timezone handling, leap-year rules, and testing tips.


Background: What is the Persian (Solar Hijri) calendar?

The Persian calendar, also called the Solar Hijri calendar, is the official calendar in Iran and Afghanistan. It’s a solar calendar based on precise astronomical observations of the vernal equinox. Key facts:

  • Year zero is the Hijra (622 CE) but Persian years are solar and align differently with Gregorian years.
  • Months are: Farvardin (1) through Esfand (12). The first six months have 31 days, next five have 30 days, and Esfand has 29 days (30 in leap years).
  • Leap years follow a complex 33-year cycle approximated by arithmetic rules in programming implementations. In practice, astronomical calculations give the most accurate results.

Methods for conversion

Three main approaches:

  1. Algorithmic conversion (calendar arithmetic):

    • Use well-known algorithms (e.g., the Iranian civil calendar algorithm) that map Gregorian dates to Julian Day Number (JDN) then to Persian date.
    • Pros: No external dependencies; fast.
    • Cons: Implementation details are tricky; leap rules approximated.
  2. Library-based conversion:

    • Use established date libraries that include Persian calendar support (e.g., moment-jalaali, persian-date, Khayyam in Python, or .NET libraries).
    • Pros: Tested, maintained, easy to use.
    • Cons: Dependency management; library updates.
  3. Server-side / astronomical conversion:

    • Use astronomical calculations to determine the true vernal equinox for higher accuracy (rarely necessary for most apps).
    • Pros: Highest accuracy.
    • Cons: Complex; requires astronomical data.

Algorithmic conversion: method overview

A commonly used approach:

  1. Convert Gregorian date to Julian Day Number (JDN).
  2. Convert JDN to Persian year/month/day using Iranian civil calendar arithmetic.

Key steps (high-level):

  • Compute the number of days since the Persian epoch (Farvardin 1 of year 1).
  • Determine the Persian year by dividing by 365 or 366 accounting for leap days.
  • Compute month and day from remaining days.

Many implementations use the algorithm by Roozbeh Pournader and Mohammad Toossi or the one in “Calendrical Calculations” by Reingold & Dershowitz.


JavaScript examples

  1. Simple, widely used algorithm (no dependencies)
// Gregorian to Persian (algorithmic) — adapted from common implementations function gregorianToJdn(gy, gm, gd) {   const a = Math.floor((14 - gm) / 12);   const y = gy + 4800 - a;   const m = gm + 12 * a - 3;   return gd + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) - 32045; } function jdnToPersian(jdn) {   const depoch = jdn - persianEpochJdn;   const cycle = Math.floor(depoch / 1029983);   let cyear = depoch % 1029983;   let ycycle;   if (cyear === 1029982) {     ycycle = 2820;   } else {     const aux1 = Math.floor(cyear / 366);     const aux2 = cyear % 366;     ycycle = Math.floor((2134 * aux1 + 2816 * aux2 + 2815) / 1028522) + aux1 + 1;   }   const year = ycycle + 2820 * cycle + 474;   const persianYear = year <= 0 ? year - 1 : year;   const yday = jdn - persianToJdn(persianYear, 1, 1) + 1;   let month = yday <= 186 ? Math.ceil(yday / 31) : Math.ceil((yday - 186) / 30) + 6;   let day = jdn - persianToJdn(persianYear, month, 1) + 1;   return { year: persianYear, month, day }; } function persianToJdn(py, pm, pd) {   const epbase = py - (py >= 0 ? 474 : 473);   const epyear = 474 + (epbase % 2820);   return pd + (pm <= 7 ? (pm - 1) * 31 : ((pm - 1) * 30 + 6)) + Math.floor((epyear * 682 - 110) / 2816) + (epyear - 1) * 365 + Math.floor(epbase / 2820) * 1029983 + (persianEpochJdn - 1); } const persianEpochJdn = 1948320.5 | 0; // JDN for 622-03-19 (approx) — use integer JDN // Usage: function gregorianToPersian(gy, gm, gd) {   const jdn = gregorianToJdn(gy, gm, gd);   return jdnToPersian(jdn); } console.log(gregorianToPersian(2025, 8, 30)); // example 

Note: The epoch constant and some integer handling may need adjustment; use tested libraries in production.

  1. Library approach (node)
npm install persian-date 
const persianDate = require('persian-date'); const pd = new persianDate([2025, 8, 30]).toCalendar('gregorian'); // example usage patterns vary console.log(pd.format()); 

Check library docs for exact APIs.


Python examples

  1. Using algorithmic conversion (based on civil calendar formulas)
def gregorian_to_jdn(gy, gm, gd):     a = (14 - gm) // 12     y = gy + 4800 - a     m = gm + 12 * a - 3     return gd + (153 * m + 2) // 5 + 365 * y + y // 4 - y // 100 + y // 400 - 32045 # Implement persian conversion functions similar to JS version above # For brevity, use the 'khayyam' or 'convertdate' library in production: # pip install convertdate import convertdate persian = convertdate.jalali.from_gregorian(2025, 8, 30) print(persian)  # (year, month, day) 
  1. Library approach
pip install convertdate 
from convertdate import jalali print(jalali.from_gregorian(2025, 8, 30))  # (1404, 6, 8) example 

C# (.NET) examples

  1. Using System.Globalization (no built-in Persian conversion to Solar Hijri prior to .NET improvements) — use third-party library:
  • Use NodaTime or PersianCalendar class in System.Globalization for UmAlQura? Actually .NET has PersianCalendar in System.Globalization that implements the Persian calendar.
using System; using System.Globalization; var pc = new PersianCalendar(); var gDate = new DateTime(2025, 8, 30); int py = pc.GetYear(gDate); int pm = pc.GetMonth(gDate); int pd = pc.GetDayOfMonth(gDate); Console.WriteLine($"{py}/{pm:D2}/{pd:D2}"); 

Note: PersianCalendar in .NET uses an arithmetic approximation; validate against requirements.


Timezone & daylight considerations

  • Convert dates in UTC or the user’s local timezone consistently before converting calendars.
  • Calendar conversion is date-based; clock/time rarely affects date except at midnight boundaries and when converting instants across timezones.

Leap years and edge cases

  • Persian leap years follow a 33-year-ish pattern in arithmetic algorithms but actual astronomical leap years may differ slightly.
  • Test conversions around:
    • Persian year beginnings (Farvardin 1 — Nowruz).
    • Gregorian Feb ⁄29 crossings.
    • Years near epoch boundaries (e.g., years far in the past/future).

Testing checklist

  • Round-trip test: Gregorian -> Persian -> Gregorian should return original date.
  • Compare library outputs (convertdate, persian-date, .NET PersianCalendar) for a sample set.
  • Test known historical dates (e.g., Persian new year 1400 = 2021-03-21).

When to prefer each method

  • Use libraries for most apps: fewer bugs, maintained.
  • Use algorithmic code if you must avoid dependencies or need embedded systems.
  • Use astronomical methods only if legal/astronomical precision for Nowruz is required.

Conclusion

Converting Gregorian to PersianDate can be done accurately with well-known algorithms or by using established libraries across languages. For most applications use a tested library; for embedded or dependency-free contexts implement the algorithm carefully and validate extensively.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *