12,502,578 members (55,567 online)
alternative version

88.2K views
45 bookmarked
Posted

# Jalali Calendar

, 17 Mar 2006
 Rate this:
This article explains a more accurate method than the algorithm that the .NET Framework's PersianCalendar uses, to deal with the Persian calendar. This method covers a wider range of dates, and also years before Common Era.

## Introduction

Jalali (Persian) calendar is the official calendar in Iran and some neighbor territories. Although Jalali is a solar calendar with strict rules, it has always been a challenge for programmers to provide some means of conversions for it and the Gregorian calendar. If you search CodeProject for terms like “jalali”, “persian” or “shamsi”, you’ll find some good codes that try to present a method for converting dates in Gregorian to dates in Persian calendar and vice versa. The Microsoft .NET Framework 2 contains the `PersianCalendar` class in the `System.Globalization` namespace. It should have solved all the problems but the truth is that the Persian calendar is not a simple periodic one as the algorithm used in the `PersianCalendar` class supposes.

The main problem is in leap years. Jalali calendar is based on the actual observation of the sun, other than established mathematical principals. The `PersianCalendar` uses an algorithm sometimes called Khayam. It assumes that a given Jalali year is a leap year if the remainder of it divided by 33 be 1, 5, 9, 13, 17, 22, or 30. This simple pattern fails for 1634, just 250 years by now. In fact the algorithm is correct for the years 1178 to 1634 Jalali (1799 to 2256 Gregorian). Here I will describe another method that covers a much wider range.

The codes and the algorithm that would be described in this article are originally written by Bill J. Gray. He kindly allowed me to port his C codes to this .NET class.

## Jalali Calendar in Details

The Jalali calendar is named after king Jalal-al-Din Malek-Shah Saljouqi. The Iranian mathematician and poet Omar Khayam has done much of the works to designate the rules of the calendar.

The new year of Jalali begins at the astronomical moment of the beginning of spring. Since not all programmers are astronomers, I will explain some astronomical terms in this article. Everybody knows that the sun moves east to west in the sky, because the earth is spinning. But if the sun was too dim that we could see other stars around it, we would have noticed another motion: the sun slowly moving from west to east across the sky. This motion is caused by the earth orbiting the sun, and it has a period of nearly 365.24 days. The fraction (0.24) is why we must have leap years in calendars; and because 0.24 is not exactly 0.25 (a quarter), the periods of leap years in the Jalali calendar are so complex. Anyway, a new year in Jalali calendar begins just exactly when the sun is located in a point in the sky we call Vernal Equinox. For simplicity, I call this moment Norooz (Norooz is the name of the new year celebrations in Iran).

Jalali calendar rules say that if Norooz happens before local midday, that day is the first day of the new year, else the following day is. Each Jalali year has 12 months. The first 6 months are all 31-days long, the remaining 5 months have 30 days, and the last month is also a 30-day month in leap years, or has 29 days otherwise.

This pattern is so interesting; at the first half of the year, the earth is farther from the sun, so it moves slower than the second half of the year when the months are 30-days long. This resembles Kepler’s third law.

## How Does It Work

All we need to do is to find the instance of vernal equinox (Norooz). If we know this moment for a given year (and its following year), then we can make that year’s calendar. There is a term in astronomy called Julian day (it has nothing to do with the Julian calendar). A Julian day is a means to express dates in real numbers other than the common y-m-d format. It would be more useful for mathematical purposes if we express dates by numbers like 2453823.92452 instead of March 29, 2006 10:11:18 UT. The .NET framework supports `TimeSpan` and `Ticks` but a Julian day is widely used in astronomical calculations. There is another advantage, the concept of a Julian day provides us a means to deal with BCE dates (see the Points of interest section). A Julian day is the days passed from midday (GMT) of January 1, -4712 Gregorian. Theoretically, the dates in any calendar can be converted to Julian day and back (I am not sure about “any”, but at least for Persian calendar, this can be done).

Although the motion of the earth is not completely periodic, there are algorithms for finding the instance of vernal equinox (of course, they are only accurate for a limited time but thousands of years). If we have a table of Julian days of vernal equinoxes over thousands of years, then we can have the Jalali calendar in that range. There are some books published in Persian that provide this method for conversion. Bill J. Gray had a better way; he introduced an algorithm that matches the previous method for Persian years between -1096 and +2327 (Gregorian years -457 to +2948).

It starts by finding the Julian day number of Norooz for a given year:

```private static int jalali_jd0(int jalali_year)
{
int rval;
if (jalali_year < LOWER_PERSIAN_YEAR)
throw new ArgumentOutOfRangeException("jalali_year",
"the value must be bigger than " +
LOWER_PERSIAN_YEAR.ToString());
for (int i = 0; i < 12; i++)
if (jalali_year < breaks[i])
{
rval = JALALI_ZERO + jalali_year * 365 +
(deltas[i] + jalali_year * 303) / 1250;
if (i < 3)  //zero point drops one day in first three blocks
rval--;
return (rval);
}
throw new ArgumentOutOfRangeException("jalali_year",
"the value must be bigger than " +
LOWER_PERSIAN_YEAR.ToString() +
" and less than " +
UPPER_PERSIAN_YEAR.ToString());
}```

It is quite straightforward, `JALALI_ZERO` is the Julian day of the first day of the Jalali year zero (which is equal to 1947954). `breaks` is an array of Jalali years while `deltas` is an array of constant numbers for the years in breaks.

If the year is outside the `LOWER_PERSIAN_YEAR` and `UPPER_PERSIAN_YEAR` values (which are -1096 and +2327), then we use another calendar system called the Modern Persian Calendar. This is completely algorithmic (and much simpler), and while it does not match Jalali, it closely follows it. The method that returns the Julian date of the first day of the year in the Modern Persian calendar is called `persian_modern_jd0()` and is available in the source code.

There is a method named `day_to_dmy()` that converts any Julian day to its corresponding date in Persian (or Gregorian) calendar. It starts by guessing the approximate calendar year for the given Julian day:

`year = (jd - JALALI_ZERO) / 365;`

Then in a loop, it finds the exact year and calculates the Julian days of the first days of that year and its following year (using the `jalali_jd0()` method), and determines if the current year is a leap year:

```// +1 to make sure the value is calculated
// for the given year not its previous year
int currentYearJD0 = jalali_jd0(year) + 1;
int nextYearJD0 = jalali_jd0(year + 1) + 1;
if(nextYearJD0 – currentYearJD0 == 366) {
//current year is a leap year
} else {
//it is a normal year
}```

The same methods exist for the Gregorian calendar. We can convert any Gregorian date to its corresponding Julian day using a simple formula provided by Jean Meeus in Astronomical Algorithms:

```double JulianDate(double y, double m, double d, double h)
{
double a,b;
h = h / 24; d = d + h;
if(m==1 || m==2)
{
m += 12; y-=1;
}
a = (int)(y / 100); b = 2 - a + (int)(a / 4);
return (int)(365.25 * y) + (int)(30.6001 * (m + 1)) + d + 1720994.5 + b;
}```

There is a reverse method that converts Julian days back to Gregorian dates. The algorithm could be found in the book. I have kept Gray’s implementation in the source code.

And now we’ve done! We can conclude the method described above as:

1. Convert Jalali date to its corresponding Julian day
2. Convert the calculated Julian day to Gregorian date

And vice versa.

## What If You Want a Jalali Calendar Out of This Range

The Jalali year range -1096 to 2327 fits all my historical needs. The Persian year of 2327 is equal to the Gregorian year 2949 and is the maximum year that the .NET Framework’s `DateTime` supports. But it may happen for you that you want date conversations out of this range. The code provided in this article simply uses the Modern Persian Calendar when it gets a date out of this range. But it is possible to provide exact conversions for dates over thousands years, actually as long as the astronomical formulae that calculate the position of the sun in the sky permits, and also as long as the variable we call Delta-T is accurate enough. I will not go farther, just know that Delta-T varies by time and its value is not known for the future years.

Again, all we need to do is to populate a table of Julian days of spring equinoxes, but instead of using the simple `jalali_jd0()` method, we need to find the moment by calculating the position of the sun in the sky. Meeus has provided some nice algorithms in his book. You can also take a look at the nice method Gray posted in his website. Dealing with Jalali calendar over a wide range of years is complex enough to be the subject of another article. If I get time, I’ll write it for CodeProject, otherwise you can find all the methods in Gray’s pages (see the Resources section).

## Using The Code

To make it all work with the .NET Framework, I made the `JalaliCalendar` class that inherits `System.Globalization.Calendar`. I also included a structure type in the source code, named `PersianDate`, which mimics the functionality of `System.DateTime`. I had written the structure about a year ago to use with the `PersianCalendar` class, and although the code is quite funny, it was a handy tool for me. I changed it a little to work with the Jalali calendar. Using the type is straightforward:

```PersianDate pd1 = new PersianDate(DateTime.Today);
PersianDate pd2 = new PersianDate(1385, 1, 13);```

The `PersianDate` type provides many properties and methods such as: `AddDays()`…, `ToString()`, `WeekOfYear`, `DaysInMonth()`, `IsLeapYear()`, `GetMonthName()`, `StaringDateOfWeek()`, and so on.

The following code demonstrates how to use `JalaliCalendar`:

```JalaliCalendar jcal = new JalaliCalendar();
DateTime dt = jcal.ToDateTime(1385, 1, 13, 18, 15, 20, 0);
Console.WriteLine("Gregorian date correspoding " +
"to 13/1/1385 18:15:20 == " + dt);
Console.WriteLine("The length of the last month in 1387 is == "
+ jcal.GetDaysInMonth(1387, 12));
Console.WriteLine("So 1387 is a leap year == " +
jcal.IsLeapYear(1387));```

Prints:

```Gregorian date correspoding
to 13/1/1385 18:15:20 == 4/2/2006 6:15:20 PM
The length of the last month in 1387 is == 30
So 1387 is a leap year == True```

## The Demo Project

I had originally written the program for my Pocket PC. Here I have slightly modified it to become a test program for Persian date conversation for .NET Framework’s `PersianCalendar` and the `JalaliCalendar` introduced here. Its source code demonstrates the usage of my `PersianDate` structure type.

## Points of Interest

The main purpose for using this `JalaiCalendar` in place of the .NET Framework’s `PersianCalendar` must be the need of date conversation for historical events. If you just want to display the current date in your website, `PersianCalendar` is sufficient. But the .NET Framework has limitations for dates before the common era (dates with a negative year), `System.DateTime` just supports dates after January 1, 1 AC. To overcome this problem, I made a structure type named `XDateTime` that supports dates in both common and before common eras. This type uses Julian days at the heart of the algorithm instead of `Ticks`. Using this method, `XDateTime` can deal with any date after January 1, 4712 BC.

The type initializes by some overridden constructors, but all of them calls one of these two methods: one that constructs the type using a calendar date (year, month …) values, and one that makes the type using a Julian day value. The methods ask you to specify if the date you are working on is expressed (or should be expressed) in Gregorian or Julian calendar. Note that the Julian calendar does not relate to a Julian day at all. For common historical uses, you must consider that the days before October 15, 1582 are in Julian calendar. There’s another thing to be mentioned, there is no year zero in history! The year before year 1 is considered to be year -1. This is why when you call the `XDateTime.ToString()` method, you’ll get something like: 4/18/53 BC, while `XDateTime.Year` property returns -52. The algorithms used here take year zero into effect, thus `XDateTime(-52,4,18)` is the constructor for 4/18/53 BC. Here are some examples:

```XDateTime xdt = new XDateTime(-400, 5, 8, 2, 25, 30, false);
Console.WriteLine(xdt);
Console.WriteLine(xdt.DayOfWeek);
Console.WriteLine(xdt);
Console.WriteLine(xdt.DayOfWeek);```

Prints:

```5/8/401 BC 2:25:30
Wednesday
5/11/401 BC 14:25:30
Saturday```

The last argument of the `XDateTime` constructor is set to `false` to indicate that the date is expressed in Julian calendar.

I have coded an `XPersianDate` structure in the same manner. This type uses the same algorithm that `JalaliCalendar` uses, to convert any Jalali date to its corresponding Julian day and Gregorian date. Here is a sample:

```XDateTime xdt = new XDateTime(-400, 5, 8, 2, 25, 30, false);
Console.WriteLine(xdt);
XPersianDate xpd = new XPersianDate(xdt.JulianDay);
Console.WriteLine(xpd);
Console.WriteLine(xpd.ToXDateTime(false)); //false: is Julian```

Prints:

```5/8/401 BC 2:25:30
13/2/1022 BH 2:25:30
5/8/401 BC 2:25:30```

I used the term “BH” to express “Before Hijrat”.

## Conclusion

Here, an accurate date conversation method for Jalali and Gregorian calendars was explained. This method is useful for special purposes such as date conversation for historical events. I also provided two structure types to deal with dates in Before Common Era.

## Resources

• Here is Bill J. Gray's algorithm[^]. I just ported his C code into C#.
• Jean Meeus’ Astronomical Algorithms[^]. The first edition of this book has been translated in Persian and published under the title of “فرمول‌های ستاره‌شناسی برای محاسب‌ها”.
• I believe this[^] is the origin of the .NET Framework’s `PersianCalendar` class. This is a nice project written by Omid K. Rad, I have used his idea and his routines in the `JalaliCalendar` class.
• Here is another article titled The Persian Calendar for 3000 years[^] that explains a similar method to Gray’s algorithm.

A list of licenses authors might use can be found here

## Share

 Web Developer United Arab Emirates
I love messing around with JavaScript, my discovery of the power of JavaScript was the biggest discovery since the time I found out I like astronomy. I spent most of my life shooting heavenly bodies, studying physics, organizing or just being a nice member of amateur astronomy groups and writing about astronomy.

I believe in fast and agile development styles, things just change for a small company before almost any design could be finalized. The programs that I create evolve. An evolved program works better and better by time, but finally nobody knows how!

Seriously, I’m a software architect with wild ideas. I enjoy working on large distributed systems, anything from remotely controlling a telescope to a network of games distributed all over the internet.

Here is the latter one, Hyzonia; I invested a good amount of time on designing and developing it. You might enjoy it if you want to spice up your website with some games or if you’re looking for a good reason to develop a casual game.

Here's my blog.

## You may also be interested in...

 Pro Pro

 First Prev Next
 My vote of 4 Amir Mohammad Nasrollahi29-Jul-13 22:10 Amir Mohammad Nasrollahi 29-Jul-13 22:10
 A Mini Bug in PersianDate.cs Houman Masnavi29-Sep-11 14:45 Houman Masnavi 29-Sep-11 14:45
 Using the date converter in MS Access? Inam Mischa7-Jan-09 0:06 Inam Mischa 7-Jan-09 0:06
 Attempting to make PHP conversion MeNot13-Jun-08 0:44 MeNot 13-Jun-08 0:44
 Salnameh Simorgh#11-Oct-06 4:08 Simorgh# 11-Oct-06 4:08
 Re: Salnameh Homam Hosseini11-Oct-06 7:47 Homam Hosseini 11-Oct-06 7:47
 Re: Salnameh Simorgh#13-Oct-06 6:35 Simorgh# 13-Oct-06 6:35
 Re: Salnameh Homam Hosseini13-Oct-06 9:07 Homam Hosseini 13-Oct-06 9:07
 Re: Salnameh Simorgh#16-Oct-06 0:33 Simorgh# 16-Oct-06 0:33
 Re: Salnameh Homam Hosseini16-Oct-06 1:16 Homam Hosseini 16-Oct-06 1:16
 [Message Deleted] Majid Shahabfar20-Mar-06 19:07 Majid Shahabfar 20-Mar-06 19:07
 Re: nice Homam Hosseini22-Mar-06 0:26 Homam Hosseini 22-Mar-06 0:26
 Last Visit: 31-Dec-99 18:00     Last Update: 25-Sep-16 20:37 Refresh 1