2

I need help to count only business days (i.e excluding Saturday and Sunday ) between two dates in xslt 1.0

Hikmat
  • 450
  • 4
  • 19
  • I'm not sure it is possible in XSLT... Depending on your XSLT processor,, you may be able to call custom functions, e.g. in [Xalan](http://xalan.apache.org/xalan-j/extensions.html) -- but your stylesheet won't be portable anymore – potame Apr 02 '15 at 12:31
  • Thanks potame for you reply. the problem is I am using this xslt in Oracle fusion middle-ware and including Xalan will be not possible. – Hikmat Apr 02 '15 at 12:48
  • Xalan may not be the only processor accepting this kind of extensions - it was but an example. Maybe Oracle XML processor provides similar features, refer to its technical documentation. – potame Apr 02 '15 at 12:56
  • No, there is no need for extensions; there are pure XSLT 1.0 solutions. – C. M. Sperberg-McQueen Apr 02 '15 at 15:45

2 Answers2

3

count only business days (i.e excluding Saturday and Sunday ) between two dates in xslt 1.0

If it can be assumed that the two given dates will not fall on Saturday or Sunday, you could use the method shown in the following example:

XSLT 1.0

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

<xsl:template match="/">
    <output>
        <workdays>
            <xsl:call-template name="duration-in-workdays">
                <xsl:with-param name="start-date" select="'2015-04-02'" />
                <xsl:with-param name="end-date" select="'2015-04-08'" />
            </xsl:call-template>
        </workdays>
    </output>
</xsl:template> 

<xsl:template name="duration-in-workdays">
    <!-- assumes start-date and end-date are both workdays -->
    <xsl:param name="start-date"/>
    <xsl:param name="end-date"/>
    <xsl:variable name="start">
        <xsl:call-template name="JDN">
            <xsl:with-param name="date" select="$start-date" />
        </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="end">
        <xsl:call-template name="JDN">
            <xsl:with-param name="date" select="$end-date" />
        </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="start-weekday" select="($start + 1) mod 7" />
    <xsl:variable name="end-weekday" select="($end + 1) mod 7" />
    <xsl:variable name="weeks" select="floor(($end - $start) div 7)" />
    <xsl:variable name="days" select="($end - $start) mod 7" />

    <xsl:value-of select="5 * $weeks + $days - 2*($start-weekday > $end-weekday)"/>
</xsl:template> 

<xsl:template name="JDN">
    <xsl:param name="date"/>
    <xsl:variable name="year" select="substring($date, 1, 4)"/>
    <xsl:variable name="month" select="substring($date, 6, 2)"/>
    <xsl:variable name="day" select="substring($date, 9, 2)"/>
    <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) + 365*$y + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045" />
</xsl:template> 

</xsl:stylesheet>

</xsl:stylesheet>

Caveat: not tested thoroughly.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
0
<xsl:template match="/">
    <xsl:value-of select="this:WorkDayDifference(xs:date('2014-05-01'),xs:date('2014-05-12'))"/>
    

</xsl:template>

    <xsl:function name="this:WorkDayDifference">
        <xsl:param name="startDate" as="xs:date"/>
        <xsl:param name="endDate" as="xs:date"/>
        <xsl:variable name="endDateDay" select="this:day-of-week($endDate)"/>
        <xsl:variable name="days" select="days-from-duration($endDate - $startDate)"/>
        <xsl:variable name="dow1" select="this:day-of-week($startDate)"/>
        <xsl:variable name="dow2" select="this:day-of-week($endDate)"/>
        <xsl:variable name="weeks" select="xs:integer($days div 7)"/>
        <xsl:variable name="offset" select="if($dow2 ge $dow1) then if($endDateDay = 6 or $endDateDay = 0)then(-6)else(-5) else if($endDateDay = 6 or $endDateDay = 0)then(-1)else(0)"/>
        <xsl:variable name="wdays" select="sum((0,1,1,1,1,1,0,0,1,1,1,1,1,0)[position() ge $dow1 + 1 and position() le ($dow2 + 7)]) + $weeks * 5 + $offset + 1"/>
        <xsl:value-of select="number($wdays)"/>
    </xsl:function>
    
    <xsl:function name="this:day-of-week" as="xs:integer?" >
        <xsl:param name="date" as="xs:anyAtomicType?"/>
        <xsl:sequence select="if (empty($date)) then () else (xs:integer((xs:date($date) - xs:date('1901-01-06')) div xs:dayTimeDuration('P1D')) mod 7)"/>
    </xsl:function>
Srini
  • 1
  • The Above code can provide Business days between two days (excluding saturday, Sunday) It works in XSLT 2.0 Business days (working days) between Jan 01, 2021 though Jan 15, 2021 == 11 days. Hope this helps for all. – Srini Jan 24 '21 at 23:38
  • This code can provide Business days between two days (excluding saturday, Sunday) It works in XSLT 2.0 Business days (working days) between Jan 01, 2021 though Jan 15, 2021 == 11 days. Hope this helps for all. – Srini Jan 24 '21 at 23:40
  • 1
    You can [edit] your answer to put the explanation there, where it belongs, instead of in comments. – Blastfurnace Jan 25 '21 at 01:46