XSL template for adding days

November 6th, 2008 | Categories: SharePoint, XSLT | Tags:

I can’t believe it’s so complex to add couple of days to a certain date. I needed an XSLT way of calculating dates with input parameters for date (format YYYY-MM-DD) and number of days (number). I know, some of you say use EXSLT. After not getting it to work, I’ve decided to do my own version.

Please note that this template is not for calculating more than one month (for example to add 50 days. And date has to be in ISO format (YYYY-MM-DD). It can be a starting point for your modifications and needs to work with dates.

<xsl:template name="calcDate">
    <xsl:param name="date"/>
    <xsl:param name="days"/>
    <xsl:param name="oldMonth"><xsl:value-of select="substring($date,6,2)"/></xsl:param>
    <xsl:param name="oldYear"><xsl:value-of select="substring($date,1,4)"/></xsl:param>
    <xsl:param name="oldDay"><xsl:value-of select="substring($date,9,2)"/></xsl:param>
    <xsl:param name="newMonth">
        <xsl:choose>
            <xsl:when test="$oldMonth = '01'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">01</xsl:when>
                    <xsl:otherwise>02</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '02'">
                <xsl:choose>
                    <xsl:when test="($oldYear mod 4 = 0 and number($oldDay) + $days &lt;= 29) or ($oldYear mod 4 != 0 and number($oldDay) + $days &lt;= 28)">02</xsl:when>
                    <xsl:otherwise>03</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '03'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">03</xsl:when>
                    <xsl:otherwise>04</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '04'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 30">04</xsl:when>
                    <xsl:otherwise>05</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '05'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">05</xsl:when>
                    <xsl:otherwise>06</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '06'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 30">06</xsl:when>
                    <xsl:otherwise>07</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '07'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">07</xsl:when>
                    <xsl:otherwise>08</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '08'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">08</xsl:when>
                    <xsl:otherwise>09</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '09'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 30">09</xsl:when>
                    <xsl:otherwise>10</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '10'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">10</xsl:when>
                    <xsl:otherwise>11</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '11'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 30">11</xsl:when>
                    <xsl:otherwise>12</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '12'">
                <xsl:choose>
                    <xsl:when test="number($oldDay) + $days &lt;= 31">12</xsl:when>
                    <xsl:otherwise>01</xsl:otherwise>
                </xsl:choose>
            </xsl:when>
        </xsl:choose>
    </xsl:param>
    <xsl:param name="newYear">
        <xsl:choose>
            <xsl:when test="$oldMonth = '12' and (number($oldDay) + $days) &gt;= 31"><xsl:value-of select="number($oldYear) + 1"/></xsl:when>
            <xsl:otherwise><xsl:value-of select="$oldYear"/></xsl:otherwise>
        </xsl:choose>
    </xsl:param>
    <xsl:param name="newDay">
        <xsl:choose>
            <xsl:when test="$oldMonth = '01'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '02'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise>
                        <xsl:choose>
                            <xsl:when test="$oldYear mod 4 = 0">
                                <xsl:value-of select="number($oldDay) + $days - 29"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="number($oldDay) + $days - 28"/>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '03'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '04'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 30"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '05'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '06'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 30"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '07'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '08'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '09'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 30"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '10'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '11'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 30"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:when test="$oldMonth = '12'">
                <xsl:choose>
                    <xsl:when test="$newMonth = $oldMonth"><xsl:value-of select="number($oldDay) + $days"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="number($oldDay) + $days - 31"/></xsl:otherwise>
                </xsl:choose>
            </xsl:when>
        </xsl:choose>
    </xsl:param>
    <xsl:value-of select="$newYear"/>
    <xsl:text>-</xsl:text>
    <xsl:value-of select="$newMonth" />
    <xsl:text>-</xsl:text>
    <xsl:if test="$newDay &lt; 10">0</xsl:if><xsl:value-of select="$newDay"/>
    </xsl:if>
</xsl:template>

Usage:

Copy-paste the upper code to the end of your XSL stylesheet (after the last </xsl:template> tag in your data view. Then in your data view you can call the template.

<xsl:call-template name=”calcDate”>
<xsl:with-param name=”date” select=”substring-before(@Created,’T')”/>
<xsl:with-param name=”days” select=”5″/>
</xsl:call-template>

This will return five days from the created date.

There probably IS a better way, I just couldn’t find it. :)

Oznake ponudnika Technorati: ,,
  1. November 7th, 2008 at 09:15
    Reply | Quote | #1

    Wow! It looks really complicated. Have you tried using custom XSLT functions (EXSLT is just an example, but you could create your own functions as well)? I have described the process on my blog @ http://blog.mastykarz.nl/extending-content-query-web-part-xslt-custom-functions/. It’s about extending the Content Query Web Part but I’m pretty sure you could do the same for any other XSLT-using Web Part.

  2. Curious in Indiana
    November 7th, 2008 at 14:40
    Reply | Quote | #2

    I’d like to something similar but need to add up to 90 days. This is interesting. However, it’s a bit beyond my reach technically. I’ve tried following the directions you gave above using SharePoint designer and I keep getting an error:

    This Web Part does not have a valid XSLT stylesheet: Error: End tag ‘xsl:when’ does not match the start tag ‘xsl:value-of’

  3. Boris Gomiunik
    November 8th, 2008 at 00:24
    Reply | Quote | #3

    Hi, Curious in Indiana!

    The problem is because of a mismatching end tag. I’ve updated the post to have easier selectable text. Perhaps the quotes were the problem. Othewise if the problem persists, please verify that you have all the <xsl:value-of … tags finishing with a slash before closing them />

  4. JCNET
    January 12th, 2010 at 17:22
    Reply | Quote | #4

    Is it just me, or is it crazy that it’s not much easier to do this CRITICAL and BASIC operation inside a SharePoint Designer XPATH Expression filter. Umm.. dateadd maybe?

  5. Boris Gomiunik
    January 25th, 2010 at 09:40
    Reply | Quote | #5

    @JCNET: I was looking for a solution, I couldn’t find anything that worked. If you know an XPATH expression that would work, please let me know.

  6. Andrew
    February 11th, 2010 at 07:17
    Reply | Quote | #6

    Very cool – I was in the same boat as you. Thanks!