Calculating Julian and Absolute Day Numbers from a Specified Date

Problem

You have a date and would like to know the corresponding Julian day number and/or Absolute day number.

Solution

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>

Discussion

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.14.245