Formatting Dates and Times

Problem

You want to format dates and times based on a format string.

Solution

These templates reuse many of the templates already presented in this chapter. The format-date-time uses a format string where %x is a formatting directive (see later) and all other text is output literally. The default format is the ISO date-time format for Gregorian dates:

<xsl:template name="date:format-date-time">
    <xsl:param name="year"/>
    <xsl:param name="month"/>
    <xsl:param name="day"/>
    <xsl:param name="hour"/>
    <xsl:param name="minute"/>
    <xsl:param name="second"/>
    <xsl:param name="time-zone"/>
    <xsl:param name="format" select="'%Y-%m-%dT%H:%M:%S%z'"/>
   
     <xsl:choose>
       <xsl:when test="contains($format, '%')">
        <xsl:value-of select="substring-before($format, '%')"/>
      </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="$format"/>
       </xsl:otherwise>
     </xsl:choose>
   
    <xsl:variable name="code"
                  select="substring(substring-after($format, '%'), 1, 1)"/>
    <xsl:choose>
   
      <!-- Abbreviated weekday name -->
      <xsl:when test="$code='a'">
        <xsl:variable name="day-of-the-week">
          <xsl:call-template name="date:calculate-day-of-the-week">
            <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:variable>
        <xsl:call-template name="date:get-day-of-the-week-abbreviation">
          <xsl:with-param name="day-of-the-week" 
             select="$day-of-the-week"/>
        </xsl:call-template>
      </xsl:when>
   
      <!-- Full weekday name -->
      <xsl:when test="$code='A'">
        <xsl:variable name="day-of-the-week">
          <xsl:call-template name="date:calculate-day-of-the-week">
            <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:variable>
        <xsl:call-template name="date:get-day-of-the-week-name">
          <xsl:with-param name="day-of-the-week" 
                          select="$day-of-the-week"/>
        </xsl:call-template>
      </xsl:when>
   
      <!-- Abbreviated month name -->
      <xsl:when test="$code='b'">
        <xsl:call-template name="date:get-month-abbreviation">
          <xsl:with-param name="month" select="$month"/>
        </xsl:call-template>
      </xsl:when>
   
      <!-- Full month name -->
      <xsl:when test="$code='B'">
        <xsl:call-template name="date:get-month-name">
          <xsl:with-param name="month" select="$month"/>
        </xsl:call-template>
      </xsl:when>
   
      <!-- Date and time representation appropriate for locale -->
      <xsl:when test="$code='c'">
        <xsl:text>[not implemented]</xsl:text>
      </xsl:when>
   
      <!-- Day of month as decimal number (01 - 31) -->
      <xsl:when test="$code='d'">
        <xsl:value-of select="format-number($day,'00')"/>
      </xsl:when>
   
      <!-- Hour in 24-hour format (00 - 23) -->
      <xsl:when test="$code='H'">
        <xsl:value-of select="format-number($hour,'00')"/>
      </xsl:when>
   
      <!-- Hour in 12-hour format (01 - 12) -->
      <xsl:when test="$code='I'">
        <xsl:choose>
          <xsl:when test="$hour = 0">12</xsl:when>
          <xsl:when test="$hour &lt; 13">
            <xsl:value-of select="format-number($hour,'00')"/>
           </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="format-number($hour - 12,'00')"/>
         </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
   
      <!-- Day of year as decimal number (001 - 366) -->
      <xsl:when test="$code='j'">
         <xsl:variable name="diff"> 
         <xsl:call-template name="date:date-difference">
           <xsl:with-param name="from-year" select="$year"/>
            <xsl:with-param name="from-month" select="1"/>
            <xsl:with-param name="form-day" select="1"/>
            <xsl:with-param name="to-year" select="$year"/>
            <xsl:with-param name="to-month" select="$month"/>
            <xsl:with-param name="to-day" select="$day"/>
         </xsl:call-template>
         </xsl:variable> 
        <xsl:value-of select="format-number($diff + 1, '000')"/>
      </xsl:when>
   
      <!-- Month as decimal number (01 - 12) -->
      <xsl:when test="$code='m'">
        <xsl:value-of select="format-number($month,'00')"/>
      </xsl:when>
   
      <!-- Minute as decimal number (00 - 59) -->
      <xsl:when test="$code='M'">
        <xsl:value-of select="format-number($minute,'00')"/>
      </xsl:when>
   
      <!-- Current locale's A.M./P.M. indicator for 12-hour clock -->
      <xsl:when test="$code='p'">
        <xsl:choose>
          <xsl:when test="$hour &lt; 12">AM</xsl:when>
          <xsl:otherwise>PM</xsl:otherwise>
        </xsl:choose>
      </xsl:when>
   
      <!-- Second as decimal number (00 - 59) -->
      <xsl:when test="$code='S'">
        <xsl:value-of select="format-number($second,'00')"/>
      </xsl:when>
   
      <!-- Week of year as decimal number, 
           with Sunday as first day of week (00 - 53) -->
      <xsl:when test="$code='U'">
        <!-- add 1 to day -->
        <xsl:call-template name="date:calculate-week-number">
          <xsl:with-param name="year" select="$year"/>
          <xsl:with-param name="month" select="$month"/>
          <xsl:with-param name="day" select="$day + 1"/>
        </xsl:call-template>
      </xsl:when>
   
      <!-- Weekday as decimal number (0 - 6; Sunday is 0) -->
      <xsl:when test="$code='w'">
        <xsl:call-template name="date:calculate-day-of-the-week">
          <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:when>
   
      <!-- Week of year as decimal number, 
           with Monday as first day of week (00 - 53) -->
      <xsl:when test="$code='W'">
        <xsl:call-template name="date:calculate-week-number">
          <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:when>
   
      <!-- Date representation for current locale -->
      <xsl:when test="$code='x'">
        <xsl:text>[not implemented]</xsl:text>
      </xsl:when>
   
      <!-- Time representation for current locale -->
      <xsl:when test="$code='X'">
        <xsl:text>[not implemented]</xsl:text>
      </xsl:when>
   
      <!-- Year without century, as decimal number (00 - 99) -->
      <xsl:when test="$code='y'">
        <xsl:value-of select="format-number($year mod 100,'00')"/>  
      </xsl:when>
   
      <!-- Year with century, as decimal number -->
      <xsl:when test="$code='Y'">
         <xsl:value-of select="format-number($year,'0000')"/>
      </xsl:when>
   
      <!-- Time-zone name or abbreviation; -->
      <!-- no characters if time zone is unknown -->
      <xsl:when test="$code='z'">
        <xsl:value-of select="$time-zone"/>
      </xsl:when>
   
      <!-- Percent sign -->
      <xsl:when test="$code='%'">
        <xsl:text>%</xsl:text>
      </xsl:when>
   
    </xsl:choose>
   
    <xsl:variable name="remainder" 
                  select="substring(substring-after($format, '%'), 2)"/>
   
    <xsl:if test="$remainder">
      <xsl:call-template name="date:format-date-time">
        <xsl:with-param name="year" select="$year"/>
        <xsl:with-param name="month" select="$month"/>
        <xsl:with-param name="day" select="$day"/>
        <xsl:with-param name="hour" select="$hour"/>
        <xsl:with-param name="minute" select="$minute"/>
        <xsl:with-param name="second" select="$second"/>
        <xsl:with-param name="time-zone" select="$time-zone"/>
        <xsl:with-param name="format" select="$remainder"/>
      </xsl:call-template>
    </xsl:if>
   
</xsl:template>
   
<xsl:template name="date:format-julian-day">
    <xsl:param name="julian-day"/>
    <xsl:param name="format" select="'%Y-%m-%d'"/>
   
    <xsl:variable name="a" select="$julian-day + 32044"/>
    <xsl:variable name="b" select="floor((4 * $a + 3) div 146097)"/>
    <xsl:variable name="c" select="$a - floor(($b * 146097) div 4)"/>
   
    <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="$b * 100 + $d - 4800 + floor($m div 10)"/>
   
    <xsl:call-template name="date:format-date-time">
      <xsl:with-param name="year" select="$year"/>
      <xsl:with-param name="month" select="$month"/>
      <xsl:with-param name="day" select="$day"/>
      <xsl:with-param name="format" select="$format"/>
    </xsl:call-template>
   
</xsl:template>

Discussion

This example was made possible by all the date work done in the prior examples. The options requiring locale are not implemented, but could be implemented using extension functions (see Chapter 12).

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

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