Subject: RE: eXSLT date:add template
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Mon, 16 Jan 2006 11:31:40 -0000
|
The XPath 2.0 functions take the same view: 29 Feb plus one year is 28 Feb.
You can't avoid surprises with date arithmetic. It's not only leap years: 31
March plus 6 months minus 6 months is 30 March.
Michael Kay
http://www.saxonica.com/
> -----Original Message-----
> From: Fraser Goffin [mailto:goffinf@xxxxxxxxxxx]
> Sent: 16 January 2006 10:58
> To: mail@xxxxxxxxxxxxxxxx
> Cc: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: eXSLT date:add template
>
> I recently had a need to do some date calculations in XSLT
> (1.0) and I
> thought it would be a good opportunity to take a look at the
> eXSLT function
> and template library.
>
> What I wanted to do was, given a start date (lets call it startDate),
> calculate a new date (lets call it endDate) to be startDate +
> 1 year - 1
> day.
>
> I settled on calling the date:add template twice, the first
> time to add the
> duration P1Y and the second time to subtract the day from the
> result of the
> first call (duration -P1D).
>
> This works fine until we get to those pesky leap year dates
> (and even for
> these I'm not saying the implementation is wrong - I am just
> looking for
> clarification of the design). The date that I have a question
> over is (not
> surprisingly) the 29th February !. An example :-
>
> Note: 2004 is a leap year.
>
> The input doc looks like this :-
>
> <eXLST_dateAdd_Test1>
> <startDate>2004-02-29</startDate>
> </eXLST_dateAdd_Test1>
>
> and the output like this :-
>
> <eXLST_dateAdd_Test1>
> <startDate>2004-02-29</startDate>
> <currentDatePlus1Year>2005-02-28</currentDatePlus1Year>
> <endDate>2005-02-27</endDate>
> </eXLST_dateAdd_Test1>
>
> Here endDate is shown as the 27th Feb. One might expect this
> to be the 28th,
> but it all depends on whether adding 1 year to the 29th Feb
> should be 28th
> Feb in the following year or 01 March. The implementation
> takes the position
> that it should be 28th Feb and therefore, subtracting 1 day
> yields 27th.
>
> This seems reasonable.
>
> BUT, if I use a startDate of 2004-2-28 I will also get the
> same result. H'mm
> now I'm not so sure, maybe adding 1 year to 29th February
> SHOULD be 01 March
> after all ??
>
> Comments
>
> Fraser.
>
> Here's the simple XSLT I was using to test with :-
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> xmlns:date="http://exslt.org/dates-and-times"
> extension-element-prefixes="date">
> <xsl:import href="../functions/add/date.add.template.xsl"/>
> <xsl:output method="xml" version="1.0" encoding="UTF-8"
> indent="yes"/>
> <xsl:template match="*|@*|text()">
> <xsl:copy>
> <xsl:apply-templates select="*|@*|text()|comment()"/>
> </xsl:copy>
> </xsl:template>
> <xsl:template match="/">
> <xsl:apply-templates/>
> </xsl:template>
> <xsl:template match="startDate">
> <xsl:copy-of select="."/>
> <!-- TASK: Add 1 Year minus 1 day -->
> <!-- Add 1 Year -->
> <xsl:variable name="currentDatePlus1Year">
> <xsl:call-template name="date:add">
> <xsl:with-param name="date-time" select="."/>
> <xsl:with-param name="duration" select="'P1Y'"/>
> </xsl:call-template>
> </xsl:variable>
> <currentDatePlus1Year><xsl:value-of
> select="$currentDatePlus1Year"/></currentDatePlus1Year>
> <!-- Subtract 1 Day -->
> <xsl:variable name="endDate">
> <xsl:call-template name="date:add">
> <xsl:with-param name="date-time"
> select="$currentDatePlus1Year"/>
> <xsl:with-param name="duration" select="'-P1D'"/>
> </xsl:call-template>
> </xsl:variable>
> <endDate>
> <xsl:value-of select="$endDate"/>
> </endDate>
> </xsl:template>
> </xsl:stylesheet>
|