Re: [xsl] Getting years from duration

Subject: Re: [xsl] Getting years from duration
From: Martin Holmes <mholmes@xxxxxxx>
Date: Sat, 8 Jun 2013 08:35:24 -0700
Perfect! You beat me to it.

Cheers,
Martin

On 13-06-08 08:09 AM, Wolfgang Laun wrote:
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"
select="year-from-date($birth)"/>
   <xsl:variable name="birthMonth" as="xs:integer"
select="month-from-date($birth)"/>
   <xsl:variable name="birthDay"   as="xs:integer"
select="day-from-date($birth)"/>
   <xsl:variable name="deathYear"  as="xs:integer"
select="year-from-date($death)"/>
   <xsl:variable name="deathMonth" as="xs:integer"
select="month-from-date($death)"/>
   <xsl:variable name="deathDay"   as="xs:integer"
select="day-from-date($death)"/>
   <xsl:choose>
     <xsl:when test="$deathMonth > $birthMonth">
       <xsl:sequence select="$deathYear - $birthYear"/>
     </xsl:when>
     <xsl:when test="$deathMonth &lt; $birthMonth">
       <xsl:sequence select="$deathYear - $birthYear - 1"/>
     </xsl:when>
     <xsl:otherwise>
       <xsl:choose>
         <xsl:when test="$deathDay >= $birthDay">
           <xsl:sequence select="$deathYear - $birthYear"/>
         </xsl:when>
         <xsl:otherwise><!-- $deathDay &lt; $birthDay -->
           <xsl:sequence select="$deathYear - $birthYear - 1"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:otherwise>
   </xsl:choose>
</xsl:function>


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 9.4.0.6.

Cheers,
Martin

.



-- Martin Holmes University of Victoria Humanities Computing and Media Centre (mholmes@xxxxxxx)

Current Thread