Joda-Time is the widely used replacement for the Java date and time classes. Home page and downloads at Sourceforge.

This project is maintained by zubinkavarana

The Persian Calendar for Joda

This project is a fork of Joda Time that adds a Joda-Time Persian Chronology and different implementations of the Persian calendar based on various different intercalation methods that have been proposed for the Persian calendar. The project also adds Julian day and JDN support to the Joda DateTime class.

What follows is an introduction to the Persian calendar, and an explanation of the classes added to Joda for Persian chronology support.

What is a Solar Calendar?

A calendar is a way of grouping days to signify the passage of time in relation to a certain purpose ~ religious, commercial, mixed purposes etc. Calendars have been used through the ages to aid in the agricultural cycles, and to celebrate festivals. The solar calender closely aligns the length of a year in days to the length of time it takes for the earth to revolve around the sun once.

Solar calenders are further divided into tropical and sidereal. For a tropical solar calendar the tropical year is reckoned by observing the passing of time between two successive March or two successive September equinoxes - usually the March equinox (called the Vernal equinox in the northern hemisphere, and Autumnal equinox in the southern hemisphere) is used as it signifies the beginning of spring in the northern hemisphere.

The equinox is a key concept in understanding the Persian chronology. An equinox is that exact time when the north pole and south pole of the earth are equidistant from the sun. The sun is directly overhead the Earth's equator and the length of day and night on this day are almost equal. have a page that describes the March equinox, and you can find further reading on the net or in your favorite encyclopedia. On an average it takes 365.242 days from one Vernal equinox to the next. Calendars compensate for the fraction of time of the day by having normal years with 365 days, and occasional leap years with 366 days. The Gregorian calendar for example, inserts a leap year every 4 years (except for century years not divisible by 400).

The Persian Jalaali Calendar

If you understand the concept of the solar tropical calendar, it's easy to understand how the Jalaali calendar works. The calendar is an observational calendar; At the end of every Jalaali year (the 19th or the 20th or March of every Gregorian year), the Vernal equinox occurs. The exact time of the equinox is recorded - if the time is before 12 PM of the day Iran Standard Time the same day from 12 AM (00 hours) is declared to be the first day of the new year. If the equinox occurs after 12 PM the next day starting 12 AM (00 hours) hours is the first day of the next year (i.e. a leap year just passed by!). It is the observational character of the calendar that lends to it's accuracy (Jalaali is one of the most accurate solar calendars),

but this is also the source of much confusion/argument about the calendars intercalation mechanism.

Administrative and commercial activities require knowledge of the calendar for future years, and to know whether they may be leap or not. To fulfill this a purely mathematical method is needed that comes close to the actual leap year cycle. Various mathematical formulas have been devised by different people or organizations to predict the leap years of the Jalaali calendar. Each methods accuracy is time-boxed (i.e at some point in the future there will be an error in the formula) because of -

  1. irregularities in the earths rotation
  2. tidal acceleration that slows the rate of the earths rotation, therefore increasing the length of days
  3. certain events that may suddenly affect the Earth's angle of rotation, for example it was reported that a recent tsunami had shifted the earths axis by a small amount

Joda Persian Chronologies

The DateTime class in Joda is instantiated with a chronology that controls the effect of operations on your DateTime instances - for example the output of plusMonths(7) will be different for Persian dates and Gregorian dates. Here's an example from the Joda sourceforge page on how a chronology is used -

DateTimeZone zone = DateTimeZone.forID("Europe/London");
Chronology coptic = CopticChronology.getInstance(zone);

// current time with coptic chronology
DateTime dt = new DateTime(coptic);

int year = dt.getYear();   // gets the current coptic year
int month = dt.getMonthOfYear(); // gets the current coptic month

This project adds the Jalaali calendar to Joda by introducing the abstract Persian chronology class, and four different concrete implementations for the Persian chronology (you can extend PersianChronology to add your own).

_The reason these varied implementations are provided is because different formulas have already been implemented in various existing software programs, and in using the Jalaali calendar in your software you may be compelled to consider the existing formulas in use in older software you are upgrading or other software services you have to integrate with.

_Class hierarchy diagram. The org.joda.time.chrono.PersianChronology class is an abstract class that extends org.joda.time.chrono.BasicChronology and provides a base implementation leaving concrete classes to provide 3 details -

  1. The average length of the year
  2. Is a given Persian year leap and
  3. The start milliseconds of the year

Equinox times based on equations by Jean Meeus

The org.joda.time.chrono.PersianChronologyMeeus class implements a leap year cycle that is based on the exact Spring equinox instant calculated from formulas published by Jean Meeus. The date times produced match equinox times published here and have an error factor of + or - 1 minute. You can also double check this from previous equinox times published at USNO. The class considers the Iran Standard Time as the longitude by default, and there is getInstance method that accepts the longitude in it's parameters in case you need to override this. Some points to ponder if you are considering using this implementation -

Omar Khayyam's 33 year cycle

The org.joda.time.chrono.PersianChronologyKhayyam class implements a leap year cycle proposed by Persian mathematician Omar Khayyam which is similar to the Gregorian calendar in that it uses a leap year once every four years, but differs in that once in a 33 year cycle it will assign a leap year on the fifth rather than fourth year. The leap years are those with a remainder (after dividing by 33) of 1, 5, 9, 13, 17, 22, 26, and 30. Some points to ponder if you are considering using this implementation -

K. Borkowski's break years based on Omar Khayyam's 33 year cycle

The org.joda.time.chrono.PersianChronologyKhayyamBorkowski class implements a leap year cycle proposed by Polish astronomer Kazimierz M. Borkowski, who further refined Khayyam's formula by using published equinox times based on formulas of Jean Meeus to find when the Khayyam formula breaks, and adding in exception routines to handle these years separately thus extending the validity of the formula for 3000 years. His paper is published here. Some points to ponder if you are considering using this implementation -

Ahmad Birashk's 2820 year cycle

The org.joda.time.chrono.PersianChronologyBirashk class implements a leap year cycle proposed by Ahmad Birashk which uses a grand cycle of 2820 years, divided into sub cycles of 128 and 132 years, further divided into 33 and 29 year cycles (source). The calendar's accuracy is worse than Khayyams and fails as early as 2025 AD. Some points to ponder if you are considering using this implementation -

Why did we write so many implementations?

In one word - Legacy. People often write code in silos and have used any one of the given formulas. But in real world usage applications will have to talk to each other at some point (for example think of an ATM network software sending messages to a legacy core banking system), and the difference in dates is best handled by providing a chronology for each of these styles, allowing you to validate and convert between them easily.