Recipe4.8.Working with the Islamic Calendar


Recipe 4.8. Working with the Islamic Calendar

Problem

You need to work with dates in the Islamic system.

It is difficult if not impossible to devise universally accepted algorithms for the Islamic calendar. This is because each month starts when the lunar crescent is first seen (by an actual human being) after a new moon. New moons can be calculated quite precisely, but the actual visibility of the crescent depends on factors such as weather and the location of the observer. It is therefore very difficult to compute accurately in advance when a new month will start. Furthermore, some Muslims depend on a local sighting of the moon, whereas others depend on a sighting by authorities somewhere in the Muslim world. Saudi Arabia is an exception, since they use astronomical calculation rather than visual sightings. The algorithms provided here can be off by a few days when computing Islamic dates far in advance.


Solution

The last day of an Islamic month can be estimated quite accurately by assigning 30 days to odd months and 29 days to even months, except during a leap year:

<xsl:template name="ckbk:last-day-of-islamic-month">      <xsl:param name="month"/>      <xsl:param name="year"/>            <xsl:variable name="islamic-leap-year"            select="(11 * $year + 14) mod 30 &lt; 11"/>            <xsl:choose>        <xsl:when test="$month mod 2 or ($month = 12 and $islamic-leap-year)">          <xsl:value-of select="30"/>        </xsl:when>        <xsl:otherwise>          <xsl:value-of select="29"/>        </xsl:otherwise>      </xsl:choose> </xsl:template>

The Islamic calendar began with the Hijra, Muhammad's emigration to Medina. For most Muslims, this date occurred on sunset of July 15, 622 AD (Julian calendar). This corresponds to absolute day 227,015, hence the offset of 227,014 in the otherwise straightforward calculation of the absolute day from the Islamic date:

<xsl:template name="ckbk:islamic-date-to-absolute-day">     <xsl:param name="year"/>     <xsl:param name="month"/>     <xsl:param name="day"/>          <xsl:value-of select="$day + 29 * ($month - 1) + floor($month div 2) + 354          * ($year - 1) + floor((11 * $year + 3) div 30) + 227014"/> </xsl:template>

The absolute day to Islamic date conversion is different from the original Lisp code from which it was adapted. I use floating-point math to avoid a search technique employed in the Lisp implementation. The authors of the Lisp code desired to keep all calculations within 24-bit integer limits while retaining the greatest accuracy. However, their techniques did not translate well to XSLT. Given that XSLT 1.0 uses only floating-point math, it does not make sense to go through pains to avoid it. The numbers used stem from the average lunar month having 29.530555... days. The month number is approximated and then adjusted if it would result in a day with value less than 1. Once the year and month are established, the day can be computed as an offset from the first day of the year:

<xsl:template name="ckbk:absolute-day-to-islamic-date">     <xsl:param name="abs-day"/>          <xsl:variable name="year"            select="floor(($abs-day - 227014) div 354.36667) + 1"/>            <xsl:variable name="month">        <xsl:variable name="a"            select="$abs-day - 227014 - floor((11 * $year + 3) div 30) -                  354 * ($year - 1)"/>        <xsl:variable name="approx" select="floor($a div 29.53056)+1"/>        <xsl:choose>          <xsl:when test="(29 * ($approx - 1) + floor($approx div 2)) -            $a &lt; 1">           <xsl:value-of select="$approx - 1"/>          </xsl:when>          <xsl:otherwise>           <xsl:value-of select="$approx"/>          </xsl:otherwise>        </xsl:choose>      </xsl:variable>            <xsl:variable name="day">        <xsl:variable name="a">          <xsl:call-template name="ckbk:islamic-date-to-absolute-day">           <xsl:with-param name="year" select="$year"/>           <xsl:with-param name="month" select="$month"/>           <xsl:with-param name="day" select="1"/>          </xsl:call-template>        </xsl:variable>        <xsl:value-of select="$abs-day - $a + 1"/>      </xsl:variable>            <xsl:value-of select="concat($year,'/',$month,'/',$day)"/>       </xsl:template>

Discussion

The Hijri or Islamic calendar is interesting because it is based on purely lunar cycles, and thus the Muslim months are not fixed within the seasons. An Islamic year is approximately 354.36 days. The first year of the Islamic calendar is denoted 1 A.H. (After Hijra), Muhammad's flight from Mecca to Medina. The Islamic calendar has deep religious significance to devout Muslims and is almost always based on visual observations of the moon. Approximate calendars can be computed in advance by using algorithms, but they should generally be used only for rough planning.

See Also

You can see the Muslim calendar in action at http://www.sufisattari.com/calendar.html.

Differences in convention among various Islamic counties are described at http://www.math.nus.edu.sg/aslaksen/calendar/islamic.shtml.




XSLT Cookbook
XSLT Cookbook: Solutions and Examples for XML and XSLT Developers, 2nd Edition
ISBN: 0596009747
EAN: 2147483647
Year: 2003
Pages: 208
Authors: Sal Mangano

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net