Recipe4.11.Determining Secular and Religious Holidays


Recipe 4.11. Determining Secular and Religious Holidays

Problem

You would like to know if a given date is a holiday.

Solution

The first type of holiday includes those that fall on the same day every year. For example, a function to determine the absolute day of American Independence for any year is simply:

<xsl:template name="ckbk:independence-day">      <xsl:param name="year"/>      <xsl:call-template name="ckbk:date-to-absolute-day">           <xsl:with-param name="month" select="7"/>           <xsl:with-param name="day" select="4"/>           <xsl:with-param name="year" select="$year"/>      </xsl:call-template> </xsl:template>

The second type of holiday falls on the same day of the week relative to the start or end of a month. You can compute those days with the help of the following utility, which wraps the k-day-on-or-before-abs-day template contained in Recipe 4.8:

<xsl:template name="ckbk:n-th-k-day">     <!-- The n'th occurance of k in the given month -->      <!-- Postive n counts from beginning of month; negative from end. -->      <xsl:param name="n"/>            <!-- k = the day of the week (0 = Sun) -->           <xsl:param name="k"/>             <xsl:param name="month"/>      <xsl:param name="year"/>          <xsl:choose>        <xsl:when test="$n > 0">          <xsl:variable name="k-day-on-or-before">           <xsl:variable name="abs-day">             <xsl:call-template name="ckbk:date-to-absolute-day">               <xsl:with-param name="month" select="$month"/>               <xsl:with-param name="day" select="7"/>               <xsl:with-param name="year" select="$year"/>             </xsl:call-template>           </xsl:variable>           <xsl:call-template name="ckbk:k-day-on-or-before-abs-day">             <xsl:with-param name="abs-day" select="$abs-day"/>             <xsl:with-param name="k" select="$k"/>           </xsl:call-template>          </xsl:variable>          <xsl:value-of select="$k-day-on-or-before + 7 * ($n - 1)"/>        </xsl:when>        <xsl:otherwise>          <xsl:variable name="k-day-on-or-before">           <xsl:variable name="abs-day">             <xsl:call-template name="ckbk:date-to-absolute-day">               <xsl:with-param name="month" select="$month"/>               <xsl:with-param name="day">                <xsl:call-template name="ckbk:last-day-of-month">                  <xsl:with-param name="month" select="$month"/>                  <xsl:with-param name="year" select="$year"/>                </xsl:call-template>               </xsl:with-param>               <xsl:with-param name="year" select="$year"/>             </xsl:call-template>           </xsl:variable>           <xsl:call-template name="ckbk:k-day-on-or-before-abs-day">             <xsl:with-param name="abs-day" select="$abs-day"/>             <xsl:with-param name="k" select="$k"/>           </xsl:call-template>          </xsl:variable>          <xsl:value-of select="$k-day-on-or-before + 7 * ($n + 1)"/>        </xsl:otherwise>      </xsl:choose>   </xsl:template>

This function assumes Gregorian dates. If you need to determine relative dates within other calendar systems, you need to write equivalent routines within those systems.

It is now easy to handle holidays like American Labor and Memorial days (the first Monday of September and the last Monday of May, respectively):

<xsl:template name="ckbk:labor-day">      <xsl:param name="year"/>      <xsl:call-template name="ckbk:n-th-k-day ">           <xsl:with-param name="n" select="1"/>           <xsl:with-param name="k" select="1"/>           <xsl:with-param name="month" select="9"/>           <xsl:with-param name="year" select="$year"/>      </xsl:call-template> </xsl:template>     <xsl:template name="ckbk:memorial-day">      <xsl:param name="year"/>      <xsl:call-template name="ckbk:n-th-k-day ">           <xsl:with-param name="n" select="-1"/>           <xsl:with-param name="k" select="1"/>           <xsl:with-param name="month" select="5"/>           <xsl:with-param name="year" select="$year"/>      </xsl:call-template> </xsl:template>

Although not a holiday, American daylight savings time can also be handled:

<xsl:template name="ckbk:day-light-savings-start">      <xsl:param name="year"/>      <xsl:call-template name="ckbk:n-th-k-day ">           <xsl:with-param name="n" select="1"/>           <xsl:with-param name="k" select="0"/>           <xsl:with-param name="month" select="4"/>           <xsl:with-param name="year" select="$year"/>      </xsl:call-template> </xsl:template>     <xsl:template name="ckbk:day-light-savings-end">      <xsl:param name="year"/>      <xsl:call-template name="ckbk:n-th-k-day ">           <xsl:with-param name="n" select="-1"/>           <xsl:with-param name="k" select="0"/>           <xsl:with-param name="month" select="10"/>           <xsl:with-param name="year" select="$year"/>      </xsl:call-template> </xsl:template>

Discussion

Covering every secular and religious holiday in each country and year is impossible. However, you can classify most holidays into two types: those that fall on the same day every year (e.g., U.S. Independence Day) in their respective calendars and those that are on a particular day of the week relative to the start or end of a month (e.g., U.S. Labor Day). Religious holidays are often simple within their native calendrical system, but can be more difficult to determine within another system. For example, Eastern Orthodox Christmas always falls on December 25 of the Julian calendar. Thus, in a Gregorian year, Eastern Orthodox Christmas can fall in the beginning, the end, or not appear at all. Since we cannot cover every religious holiday in every faith, please explore the references mentioned in this chapter's introduction.




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