Recipe4.1.Calculating the Day of the Week


Recipe 4.1. Calculating the Day of the Week

Problem

Given the year, month, and day, you want to determine the day of the week.

Solution

XSLT 1.0

The following calculation does the trick and returns an integer in the range of 0-6, where 0=Sunday.

  <xsl:template name="ckbk:calculate-day-of-the-week">     <xsl:param name="date-time"/>     <xsl:param name="date" select="substring-before($date-time,'T')"/>     <xsl:param name="year" select="substring-before($date,'-')"/>     <xsl:param name="month"            select="substring-before(substring-after($date,'-'),'-')"/>     <xsl:param name="day" select="substring-after(substring-after($date,'-'),'-')"/>          <xsl:variable name="a" select="floor((14 - $month) div 12)"/>     <xsl:variable name="y" select="$year - $a"/>     <xsl:variable name="m" select="$month + 12 * $a - 2"/>         <xsl:value-of select="($day + $y + floor($y div 4) - floor($y div 100)      + floor($y div 400) + floor((31 * $m) div 12)) mod 7"/>       </xsl:template>

XSLT 2.0

Use format-date to get the day of the week as a number or a language-dependent string.

Discussion

You will notice that these equations and those in other examples make judicious use of the XPath floor( ) function. This is the only way to emulate integer arithmetic in XSLT 1.0, since all numbers are represented in floating point internally. The reason why this calculation works has to do with intricacies of the Gregorian calendar that are not particularly relevant to XSLT. For example, the fact that 97 leap years occur every 400 years so that every year divisible by 4 is a leap year, except if it is divisible by 100 and not divisible by 400, explains the final calculation. For further information, see Sidebar 1.

The Logic Behind the Math

Claus Tøndering was kind enough to clear up the mystery behind these calculations.

To get the formulas to work, first perform these calculations:

a = (14 - month) / 12 y = year - a m = month + 12*a - 2

These calculations move the start of the year from January 1 to March 1. Since a=1 for January and February and 0 for all other months, 1 is subtracted from the year in these two months. Similarly, m becomes 1 for March, 2 for April, . . . , 10 for December, 11 for January, and 12 for February.

Once these three calculations are performed, you have a year that starts on March 1. This result gives two advantages. First, it means that the leap day is placed at the end of the year, which makes calculations simpler. Second, it means that the lengths of the months follow a simple pattern:

31 30 31 30 31 (March-July) 31 30 31 30 31 (August-December) 31 X (January-February)

This setup enables you to use the expression (31*m)/12 to calculate the weekday offset in each month.





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