You have a date and would like to know the corresponding Julian day number and/or Absolute day number.
This template will give you the Julian day, given the year, month, and day:
<xsl:template name="date:calculate-julian-day"> <xsl:param name="year"/> <xsl:param name="month"/> <xsl:param name="day"/> <xsl:variable name="a" select="floor((14 - $month) div 12)"/> <xsl:variable name="y" select="$year + 4800 - $a"/> <xsl:variable name="m" select="$month + 12 * $a - 3"/> <xsl:value-of select="$day + floor((153 * $m + 2) div 5) + $y * 365 + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045"/> </xsl:template>
Once you have a way to calculate the Julian day number, it is easy to create a template for determining the number of days between any two dates:
<xsl:template name="date:date-difference"> <xsl:param name="from-year"/> <xsl:param name="from-month"/> <xsl:param name="from-day"/> <xsl:param name="to-year"/> <xsl:param name="to-month"/> <xsl:param name="to-day"/> <xsl:variable name="jd1"> <xsl:call-template name="date:calculate-julian-day"> <xsl:with-param name="year" select="$from-year"/> <xsl:with-param name="month" select="$from-month"/> <xsl:with-param name="day" select="$from-day"/> </xsl:call-template> </xsl:variable> <xsl:variable name="jd2"> <xsl:call-template name="date:calculate-julian-day"> <xsl:with-param name="year" select="$to-year"/> <xsl:with-param name="month" select="$to-month"/> <xsl:with-param name="day" select="$to-day"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="$jd1 - $jd2"/> </xsl:template>
The following templates convert from a
Julian day to a Gregorian date in the form YYYY/MM/DD. Use
substring-before
,
substring-after
, and translate
to parse or convert to the conventions of a particular locale:
<xsl:template name="date:julian-day-to-julian-date"> <xsl:param name="j-day"/> <xsl:call-template name="date:julian-or-gregorian-date-elem"> <xsl:with param name="b" select="0"/> <xsl:with param name="c" select="$j-day + 32082"/> </xsl:call-template> </xsl:template> <xsl:template name="date:julian-day-to-gregorian-date"> <xsl:param name="j-day"/> <xsl:variable name="a" select="$j-day + 32044"/> <xsl:variable name="b" select="floor((4 * $a + 3) div 146097)"/> <xsl:variable name="c" select="$a - 146097 * floor($b div 4)"/> <xsl:call-template name="date:julian-or-gregorian-date-elem"> <xsl:with param name="b" select="$b"/> <xsl:with param name="c" select="$c"/> </xsl:call-template> </xsl:template> <!-- A utility that is used for both Gregorian and Julian calendars. --> <xsl:template name="date:julian-or-gregorian-date-elem"> <xsl:param name="b"/> <xsl:param name="c"/> <xsl:variable name="d" select="floor((4 * $c + 3) div 1461)"/> <xsl:variable name="e" select="$c - floor((1461 * $d) div 4)"/> <xsl:variable name="m" select="floor((5 * $e + 2) div 153)"/> <xsl:variable name="day" select="$e - floor((153 * $m + 2) div 5) + 1"/> <xsl:variable name="month" select="$m + 3 - (12 * floor($m div 10))"/> <xsl:variable name="year" select="100 * $b + $d - 4800 + floor($m div 10)"/> <xsl:value-of select="concat($year,'/',$month,'/',$day)"/> </xsl:template>
You can easily convert between Julian days and Absolute days with the following templates:
<xsl:template name="date:julian-day-to-absolute-day"> <xsl:param name="j-day"/> <xsl:value-of select="$j-day - 1721425"/> </xsl:template> <xsl:template name="date:absolute-day-to-julian-day"> <xsl:param name="abs-day"/> <xsl:value-of select="$abs-day + 1721425"/> </xsl:template>
You can then express Absolute day/Gregorian conversions in terms of the existing Julian day/Gregorian conversions:
<xsl:template name="date:date-to-absolute-day"> <xsl:param name="year"/> <xsl:param name="month"/> <xsl:param name="day"/> <xsl:call-template name="date:julian-day-to-absolute-day"> <xsl:with-param name="j-day"> <xsl:call-template name="date:date-to-julian-day"> <xsl:with-param name="year" select="$year"/> <xsl:with-param name="month" select="$month"/> <xsl:with-param name="day" select="$day"/> </xsl:call-template> </xsl:with-param> </xsl:call-template> </xsl:template> <xsl:template name="date:absolute-day-to-date"> <xsl:param name="abs-day"/> <xsl:call-template name="date:julian-day-to-date"> <xsl:with-param name="j-day"> <xsl:call-template name="date:absolute-day-to-julian-day"> <xsl:with-param name="abs-day" select="$abs-day"/> </xsl:call-template> </xsl:with-param> </xsl:call-template> </xsl:template>
The Julian day and Absolute day are useful because they greatly simplify other date algorithms. Other examples in this chapter reuse these conversions extensively. These numbering schemes act as a common currency for all the calendar systems in this chapter. Should you ever find yourself needing to convert a Hebrew date to a Muslim date, the sequence Muslim to Absolute to Hebrew will do the trick.