ABHISHEK TRIVEDI
ABHISHEK TRIVEDI

Reputation: 1

XSLT mapping in SOA transformation to get max date from last month

I am trying to create an XSLT mapping to get the last(max) day of the previous month.

Eg- If I pass a value of 2019-10-17 to the mapping it should return 2019-09-30. The date format that I am using here is YYYY-MM-DD.

tried to get the month from the current data and subtract it with 1 so that it would return the previous month. But I am not able to get the max date of the last month.

xp20:month-from-dateTime (/ns0:ddSelecCorpoMasterOutputCollection/ns0:ddSelecCorpoMasterOutput/ns0:FROM_DATE_FILTER ) - 1

input- sysdate
o/p- maxdate of previous month
eg- i/p-2019-10-18
o/p- 2019-09-30

Thanks in advance.

Upvotes: 0

Views: 559

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 117140

Finding the last day of previous month in pure XSLT 1.0:

<xsl:template name="end-of-last-month">
    <xsl:param name="date"/>
    <!-- extract date components -->
    <xsl:variable name="year" select="substring($date, 1, 4)"/>
    <xsl:variable name="month" select="substring($date, 6, 2)"/>
    <!-- go one month back -->
    <xsl:variable name="y" select="$year - ($month = 1)"/>
    <xsl:variable name="m" select="($month + 10) mod 12 + 1"/>
    <!-- get month length -->
    <xsl:variable name="cal" select="'312831303130313130313031'"/>
    <xsl:variable name="leap" select="not($y mod 4) and $y mod 100 or not($y mod 400)"/>
    <xsl:variable name="month-length" select="substring($cal, 2*($m - 1) + 1, 2) + ($m=2 and $leap)" />
    <!-- output -->
    <xsl:value-of select="$y" />
    <xsl:value-of select="format-number($m, '-00')" />
    <xsl:text>-</xsl:text>
    <xsl:value-of select="$month-length" />
</xsl:template>

Example:

XML

<input>
    <date>2019-01-15</date>
    <date>2019-02-15</date>
    <date>2019-03-15</date>
    <date>2019-04-15</date>
    <date>2019-05-15</date>
    <date>2019-06-15</date>
    <date>2019-07-15</date>
    <date>2019-08-15</date>
    <date>2019-09-15</date>
    <date>2019-10-15</date>
    <date>2019-11-15</date>
    <date>2019-12-15</date>
    <date>2020-01-15</date>
    <date>2020-02-15</date>
    <date>2020-03-15</date>
</input>

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="/input">
    <output>
        <xsl:for-each select="date">
            <end-of-last-month date="{.}">
                <xsl:call-template name="end-of-last-month">
                    <xsl:with-param name="date" select="."/>
                </xsl:call-template>
            </end-of-last-month>
        </xsl:for-each>
    </output>
</xsl:template>

<xsl:template name="end-of-last-month">
    <xsl:param name="date"/>
    <!-- extract date components -->
    <xsl:variable name="year" select="substring($date, 1, 4)"/>
    <xsl:variable name="month" select="substring($date, 6, 2)"/>
    <!-- go one month back -->
    <xsl:variable name="y" select="$year - ($month = 1)"/>
    <xsl:variable name="m" select="($month + 10) mod 12 + 1"/>
    <!-- get month length -->
    <xsl:variable name="cal" select="'312831303130313130313031'"/>
    <xsl:variable name="leap" select="not($y mod 4) and $y mod 100 or not($y mod 400)"/>
    <xsl:variable name="month-length" select="substring($cal, 2*($m - 1) + 1, 2) + ($m=2 and $leap)" />
    <!-- output -->
    <xsl:value-of select="$y" />
    <xsl:value-of select="format-number($m, '-00')" />
    <xsl:text>-</xsl:text>
    <xsl:value-of select="$month-length" />
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <end-of-last-month date="2019-01-15">2018-12-31</end-of-last-month>
   <end-of-last-month date="2019-02-15">2019-01-31</end-of-last-month>
   <end-of-last-month date="2019-03-15">2019-02-28</end-of-last-month>
   <end-of-last-month date="2019-04-15">2019-03-31</end-of-last-month>
   <end-of-last-month date="2019-05-15">2019-04-30</end-of-last-month>
   <end-of-last-month date="2019-06-15">2019-05-31</end-of-last-month>
   <end-of-last-month date="2019-07-15">2019-06-30</end-of-last-month>
   <end-of-last-month date="2019-08-15">2019-07-31</end-of-last-month>
   <end-of-last-month date="2019-09-15">2019-08-31</end-of-last-month>
   <end-of-last-month date="2019-10-15">2019-09-30</end-of-last-month>
   <end-of-last-month date="2019-11-15">2019-10-31</end-of-last-month>
   <end-of-last-month date="2019-12-15">2019-11-30</end-of-last-month>
   <end-of-last-month date="2020-01-15">2019-12-31</end-of-last-month>
   <end-of-last-month date="2020-02-15">2020-01-31</end-of-last-month>
   <end-of-last-month date="2020-03-15">2020-02-29</end-of-last-month>
</output>

Demo: https://xsltfiddle.liberty-development.net/94AbWB5

Upvotes: 1

Michael Kay
Michael Kay

Reputation: 163595

If you have access to the XPath 2.0 date/time library,

(1) convert to an xs:date

<xsl:variable name="d" select="xs:date($in)"/>

(2) extract the day of the month:

<xsl:variable name="dom" select="day-from-date($d)"/>

(3) subtract this number of days from the date:

<xsl:variable name="result" select="$d - xs:dayTimeDuration('P1D') * $dom"/>

Upvotes: 0

Related Questions