Lorna Guttormson
Lorna Guttormson

Reputation: 48

Can a date be converted to day-of-week month dd within xsl?

I am using an xsl stylesheet to extract and display selected data from an xml file on a website.

One of the data elements is a date in the format yyyy-mm-dd. I would like to display it as, for example, Wed. May 10. Is this possible?

My overall project is to take an xml file, extract 3 data elements and put them out in a sorted order with the date display modified. I have a js for this conversion, but without the sorting. It seemed that xsl was the answer to the sorting question but now I don't know how to (or if I can) 'intercept' the date and apply a js conversion to it and put it out in the statement: xsl:value-of select="StartTime/Date"

Upvotes: 2

Views: 4114

Answers (3)

artemnih
artemnih

Reputation: 4209

You can use ddwrt:FormatDate()

<xsl:value-of select="ddwrt:FormatDate(string(@EventDate), 1033, 3)" />

The result will look like this:

Thursday, May 8, 2014

More Info On ddwrt

Upvotes: -1

Daniel Haley
Daniel Haley

Reputation: 52878

As LarsH mentioned, this is much easier in XSLT 2.0. Here's another 1.0 option if you don't have any dates earlier than 1901-01-07.

XML Input (Thanks Borodin!)

<document>
    <date>2013-01-01</date>
    <date>2013-05-24</date>
    <date>2013-12-25</date>
    <date>1957-07-13</date>
    <date>1901-01-07</date>
</document>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="date">
        <xsl:variable name="weekday" select="((xs:date(.) - xs:date('1901-01-06')) div xs:dayTimeDuration('P1D')) mod 7"/>
        <xsl:variable name="month" select="substring(.,6,2)"/>
        <xsl:copy>
            <xsl:call-template name="getWeekday">
                <xsl:with-param name="weekday" select="$weekday"/>
            </xsl:call-template>
            <xsl:call-template name="getMonth">
                <xsl:with-param name="month" select="$month"/>
            </xsl:call-template>
            <xsl:value-of select="substring(.,9,2)"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template name="getWeekday">
        <xsl:param name="weekday"/>
        <xsl:choose>
            <xsl:when test="$weekday=1">Mon. </xsl:when>
            <xsl:when test="$weekday=2">Tue. </xsl:when>
            <xsl:when test="$weekday=3">Wed. </xsl:when>
            <xsl:when test="$weekday=4">Thu. </xsl:when>
            <xsl:when test="$weekday=5">Fri. </xsl:when>
            <xsl:when test="$weekday=6">Sat. </xsl:when>
            <xsl:when test="$weekday=7">Sun. </xsl:when>
        </xsl:choose>       
    </xsl:template>

    <xsl:template name="getMonth">
        <xsl:param name="month"/>
        <xsl:choose>
            <xsl:when test="$month='01'">Jan </xsl:when>
            <xsl:when test="$month='02'">Feb </xsl:when>
            <xsl:when test="$month='03'">Mar </xsl:when>
            <xsl:when test="$month='04'">Apr </xsl:when>
            <xsl:when test="$month='05'">May </xsl:when>
            <xsl:when test="$month='06'">Jun </xsl:when>
            <xsl:when test="$month='07'">Jul </xsl:when>
            <xsl:when test="$month='08'">Aug </xsl:when>
            <xsl:when test="$month='09'">Sep </xsl:when>
            <xsl:when test="$month='10'">Oct </xsl:when>
            <xsl:when test="$month='11'">Nov </xsl:when>
            <xsl:when test="$month='12'">Dec </xsl:when>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

Output

<document>
   <date>Tue. Jan 01</date>
   <date>Fri. May 24</date>
   <date>Wed. Dec 25</date>
   <date>Sat. Jul 13</date>
   <date>Mon. Jan 07</date>
</document>

Upvotes: 0

Borodin
Borodin

Reputation: 126742

XSLT is quite capable of basic arithmetic, and the day of the week can be derived using Zeller's formula.

You would need to call the template from your own code using

<xsl:call-template name="date-format">
  <xsl:with-param name="yyyy-mm-dd" select="StartTime/Date"/>
</xsl:call-template>

This stylesheet

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="date">
    <xsl:copy>
      <xsl:call-template name="date-format">
        <xsl:with-param name="yyyy-mm-dd" select="."/>
      </xsl:call-template>
    </xsl:copy>
  </xsl:template>

  <xsl:template name="date-format">
    <xsl:param name="yyyy-mm-dd"/>

    <xsl:variable name="yyyy" select="substring-before($yyyy-mm-dd, '-')"/>
    <xsl:variable name="mm-dd" select="substring-after($yyyy-mm-dd, '-')"/>
    <xsl:variable name="mm" select="substring-before($mm-dd, '-')"/>
    <xsl:variable name="dd" select="substring-after($mm-dd, '-')"/>

    <xsl:variable name="Y">
      <xsl:choose>
        <xsl:when test="$mm &lt; 3"><xsl:value-of select="$yyyy - 1"/></xsl:when>
        <xsl:otherwise><xsl:value-of select="$yyyy + 0"/></xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="y" select="$Y mod 100"/>
    <xsl:variable name="c" select="floor($Y div 100)"/>
    <xsl:variable name="d" select="$dd+0"/>
    <xsl:variable name="m">
      <xsl:choose>
        <xsl:when test="$mm &lt; 3"><xsl:value-of select="$mm + 12"/></xsl:when>
        <xsl:otherwise><xsl:value-of select="$mm + 0"/></xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="w" select="($d + floor(($m + 1) * 2.6) + $y + floor($y div 4) + floor($c div 4) - $c * 2 - 1) mod 7"/>

    <xsl:variable name="www">
      <xsl:choose>
        <xsl:when test="$w = 0">Sun</xsl:when>
        <xsl:when test="$w = 1">Mon</xsl:when>
        <xsl:when test="$w = 2">Tue</xsl:when>
        <xsl:when test="$w = 3">Wed</xsl:when>
        <xsl:when test="$w = 4">Thu</xsl:when>
        <xsl:when test="$w = 5">Fri</xsl:when>
        <xsl:when test="$w = 6">Sat</xsl:when>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="mmm">
      <xsl:choose>
        <xsl:when test="$mm =  1">Jan</xsl:when>
        <xsl:when test="$mm =  2">Feb</xsl:when>
        <xsl:when test="$mm =  3">Mar</xsl:when>
        <xsl:when test="$mm =  4">Apr</xsl:when>
        <xsl:when test="$mm =  5">May</xsl:when>
        <xsl:when test="$mm =  6">Jun</xsl:when>
        <xsl:when test="$mm =  7">Jul</xsl:when>
        <xsl:when test="$mm =  8">Aug</xsl:when>
        <xsl:when test="$mm =  9">Sep</xsl:when>
        <xsl:when test="$mm = 10">Oct</xsl:when>
        <xsl:when test="$mm = 11">Nov</xsl:when>
        <xsl:when test="$mm = 12">Dec</xsl:when>
      </xsl:choose>
    </xsl:variable>

    <xsl:value-of select="concat($www, '. ', $mmm, ' ', $d)"/>

  </xsl:template>

</xsl:stylesheet>

applied to this XML data

<?xml version="1.0" encoding="UTF-8"?>
<document>
  <date>2013-01-01</date>
  <date>2013-05-24</date>
  <date>2013-12-25</date>
  <date>1957-07-13</date>
  <date>1776-07-04</date>
</document>

produces this output, as required

<?xml version="1.0" encoding="utf-8"?>
<document>
   <date>Tue. Jan 1</date>
   <date>Fri. May 24</date>
   <date>Wed. Dec 25</date>
   <date>Sat. Jul 13</date>
   <date>Thu. Jul 4</date>
</document>

Upvotes: 4

Related Questions