Computer Algorithm
To implement Khmer Lunar Calendar method mentioned earlier as a computer program, we first need a start date to apply this method. This date can go back to the start of the calendar system. But for practical purpose, I am going to chose January 1, 1900 AD in Gregorian calendar. This date will be called an epoch. The associate Khmer Epoch is 1 Keit of Bos (second month). This Khmer date is calculated by extrapolating the existing the data using the same method.
Epoch Date: January 1, 1900
Associate Khmer Epoch Date:
epoch_year = 1900;
khmer_month = 2;
khmer_day = 1;
Next, we will start iterate from the Epoch year to the calendar year we want to show. We start of by saving off the Epoch month and day into $newm and $newd respectively.
newm = epoch_month;
newd = epoch_day;
Calendar Arithmetic
We need to update the $newm and $newd per each iteration. In order to perform this update, we need to know how many days in a Gregorian year. This function (is_gregorian_leap) determines if a year is a Gregorian leap year or not. See the code section for detail implementation of this function. If a year a Gregorian year is a leap year then it has 366 days and 365 days if it is not. We save this in $gnumday variable.
// get number of days in a Gregorian year
if (is_gregorian_leap(year)) {
gnumday = 366;
}
else {
gnumday = 365;
}
Then we find the number of days that differ in Gregorian year and Khmer year. The number of days in Khmer year is determined by the type of Khmer year (discuss in the next section). If it is a leap-day year the number of days is 355 days, a leap-month year is 384 days, and a normal year is 354 days.
// get number of days in a Khmer year
if (is_khmer_leap_month(year)) {
knumday = 384;
}
else if (is_khmer_leap_day(year)) {
knumday = 355;
} else {
knumday = 354;
}
// find the different between gnumday and knumday
diff = gnumday - knumday;
From the differences in number of days above (diff), we can update newm and newd for that year. This update is using the fact that if Khmer year is shorter or longer than Gregorian year by x number of days, we just subtract or add from the current KhmerDay and KhmerMonth respectively.
This method is done by determining how many days in a particular Khmer month in case the subtraction or addition goes pass the valid number of day in Khmer month (1 to 29 or 30).
// find newd, newm of Khmer date
newd = newd + diff;
maxday = get_numofday_in_kmonth(newm, year);
// if newd is bigger the number of day in
// in that month, adjust the newm and newd
while(newd > maxday) {
newd = newd - maxday;
newm++;
maxday = get_numofday_in_kmonth(newm, year);
}
// if newd is negative (case of subtraction)
while (newd <= 0) {
newd = get_numofday_in_kmonth(newm - 1, year)
+ newd;
newm--;
}
In this iteration, the Khmer month and day would result in January 1, 1901.
The iteration repeats until the year matches the year we want to show. At the end of the iteration, we know that Khmer date for the beginning of the year to display. This is saved in $newm and $newd for Khmer month and day respectively.
Now we can discuss about how to determine the type of year for Khmer calendar. We will start by identify the Metonic cycle index (1 through 19). From the existing data, we can find Meton index number as:
meton_index = ((year - 2) modulus 19) + 1.
If the MetonIndex matches one of the following numbers: 3, 6, 8, 11, 14, 17, and 19, the year is identified as a leap-month year.
For a leap-day year, we have two cases.
- If the MetonIndex is 1, 4, or 10, it is a leap-day year.
- But if the MetonIndex is 15, it is a leap-day year except the following conditions: Every 76 years, it is not a leap-day year (i.e. 1916, 1992, 2068): if (year modulus 76 = 16) Every 494 years, it is not a leap-day year (i.e. 2087, 1581) if (year modulus 494 = 111)
This maybe a brute force implementation but it helps to correct the error as it accumulated over several Metonic cycles.
If the year is not a leap-day year or leap-month year, it must be a normal year with 354 days.
After knowing the KhmerDay and KhmerMonth for a given year, we can display the monthly calendar with Khmer date. We first need to identify if the given Khmer year is a normal, leap-day, or leap-month year.
If it is a normal year, we know that there are 12 months in that year and the number of days per month can be found in the appendix. Notice that the month of Jays is 29.
If it a leap-day year, everything is the same as above except Jays has 30 days instead of 29 days.
If it is a leap-month year, there are 13 months for that year and the month of Ashad become 2 months (Badhamasad and Thutiyasad) with 30 days each. Note that the month of Jays has 29 days.
Khmer Monthly Calendar Utility
From the algorithm above, I can create a Khmer monthly calendar. Khmer calendar typically added specific the moon phases. We can use the Khmer day to determine the moon phases. If the Khmer day is 8 (8 Keit), it is a first quarter and 15 (15 Keit) is a full moon. If it is the last day of the Khmer month which is 29 or 30 (14 Roaj or 15 Roaj), it is a new moon.
There are also specific types of day that are added to the calendar. For example Tgnai Koar, Tgnai Pengboramei, and Tgnai Sel are usually shown in Khmer calendar. See Khmer Terminologies in the appendix for more detail on how to add these types of day.
It is important to display the Khmer associated months in the calendar. One Gregorian month can span exactly one Khmer month or it can span up to three months. To accommodate the possibilities, I use three different color codes to identify the month. The Khmer date shown each day will have the color that corresponds to the month.
A calendar cannot be complete without display the year. The most used era in Khmer calendar is Buddhist Era (BE). To find BE year, we just add 544 to the current Gregorian year. Be aware that BE year is incremented in Khmer New Year day. The date is typically fall in April. See the section about Songkran date for more detail. The following is the pseudo code for determining the BE.
if (current_month < april) {
BE = current_year + 543;
} else {
BE = current_year + 544;
}
Khmer also uses Moha Sakaraj (MS)1 and Jolak Sakaraj (JS)2. The following shows the pseudo code of calculating the MS and JS.
MS = current_year - 78; JS = current_year - 638;
The religious events can also be added to the calendar by using the Khmer date. See the appendix for religious events.
An important aspect of the Khmer holiday is the Khmer New Year's day. For this part, Dershowitz and Reingold have the algorithm for generating New Year's day. The method implemented in Java is called:
HinduSolar.meshaSamkranti()
But as I pointed out later, the actual time does not coincide with Khmer New Year. The error ranges from 20 minutes to over an hour. But this is close enough to determine the New Year day.
Sample Computer Programs
See the Calendar Tools section more information about the web utilities and source codes on related materials.
This is a sample utility that displays Khmer Chhankitek calendar. The implementation is done using PHP.
Next: Khmer New Year >>