[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Getting years from duration

Subject: Re: [xsl] Getting years from duration
From: Wolfgang Laun <wolfgang.laun@xxxxxxxxx>
Date: Sat, 8 Jun 2013 17:09:41 +0200

Here's a simple function that avoids all problems arising from the
conversion of two dates to a duration. Age in completed years can be
computed by a simple comparison of months and days:

<xsl:function name="wl:age-in-years" as="xs:integer">
  <xsl:param name="birth" as="xs:date"/>
  <xsl:param name="death" as="xs:date"/>
  <xsl:variable name="birthYear"  as="xs:integer"
  <xsl:variable name="birthMonth" as="xs:integer"
  <xsl:variable name="birthDay"   as="xs:integer"
  <xsl:variable name="deathYear"  as="xs:integer"
  <xsl:variable name="deathMonth" as="xs:integer"
  <xsl:variable name="deathDay"   as="xs:integer"
    <xsl:when test="$deathMonth > $birthMonth">
      <xsl:sequence select="$deathYear - $birthYear"/>
    <xsl:when test="$deathMonth &lt; $birthMonth">
      <xsl:sequence select="$deathYear - $birthYear - 1"/>
        <xsl:when test="$deathDay >= $birthDay">
          <xsl:sequence select="$deathYear - $birthYear"/>
        <xsl:otherwise><!-- $deathDay &lt; $birthDay -->
          <xsl:sequence select="$deathYear - $birthYear - 1"/>

On 08/06/2013, Martin Holmes <mholmes@xxxxxxx> wrote:
> We came up against what looked like a very simple XPath issue today, and
> hit a brick wall with it. Given data that looks like this:
>          <person role="author">
>            <persName>Milton, John</persName>
>            <birth when="1600-12-09"/>
>            <death when="1674-11-08"/>
>          </person>
> we want to calculate the age of the person at death. So we thought:
> subtract the death date from the birth date to get a duration, then
> extract the years from the duration:
>    <xsl:template match="person">
>      <xsl:variable name="life" select="xs:date(death/@when) -
> xs:date(birth/@when)"/>
>      <xsl:variable name="age" select="years-from-duration($life)"/>
>      <xsl:text>Age at death: </xsl:text>
>      <xsl:value-of select="$age"/>
>    </xsl:template>
> However, the only value we were able to get back, after trying all
> manner of permutations and casts, was zero. It appears that what comes
> back from the date subtraction (which I think uses the
> op:subtract-dates() operator) is always an xs:dayTimeDuration, and that
> cannot AFAIKS be manipulated into anything from which a year can be
> extracted.
> It's always possible to get the number of days and divide by 365.25, but
> it seems strange to have to do that. Given the range of date- and
> duration-related functions, I'm sure there must be some better way of
> getting the result. Does anyone know?
> This is using Saxon
> Cheers,
> Martin

Current Thread