XSLT:两个日期之间的年份差异

发布于 2025-01-15 08:41:27 字数 386 浏览 1 评论 0原文

我想计算 XSLT 2.0 中两个日期之间的年份差异。我尝试过:

xs:dayTimeDuration(xs:date('2007-03-02')-xs:date('2002-03-01'))

给我天数的差异:

P1827D

有一个函数可以计算两个日期之间的年、月和天的某种“标准化”xs:duration ,就像本例中的 P1Y0M1D 一样,我可以从中提取年份 P1Y 。如上所述,从仅由天组成的 xs:duration 中提取年份是不可能的(也没有多大意义)。

那么如何计算两个日期的相差年数而不是天数呢?

I would like to compute the year difference between two dates in XSLT 2.0. I tried:

xs:dayTimeDuration(xs:date('2007-03-02')-xs:date('2002-03-01'))

giving me the difference in days:

P1827D

What would help would be a function that calculates a somehow "normalized" xs:duration in years, months and days between two dates, like P1Y0M1D in this example, which I can extract the year P1Y from. Extracting a year from an xs:duration consisting of days only, as above, is not possible (and wouldn't make much sense either).

So how do I compute the difference of two dates in years, not in days?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叫思念不要吵 2025-01-22 08:41:27

我猜(!)您想要返回一个相当于以整年表示的年龄的结果,使用习惯规则,即年龄在每个生日时增加一。这可以使用以下模板(您可以将其转换为函数)来计算:

<xsl:template name="age-in-years">
    <xsl:param name="start-date"/>
    <xsl:param name="end-date"/>
    
    <xsl:variable name="start-year" select="year-from-date($start-date)"/>
    <xsl:variable name="start-month" select="month-from-date($start-date)"/>
    <xsl:variable name="start-day" select="day-from-date($start-date)"/>
    
    <xsl:variable name="end-year" select="year-from-date($end-date)"/>
    <xsl:variable name="end-month" select="month-from-date($end-date)"/>
    <xsl:variable name="end-day" select="day-from-date($end-date)"/>

    <xsl:value-of select="$end-year - $start-year - number(100 * $end-month + $end-day lt 100 * $start-month + $start-day)" />
</xsl:template> 

请注意,这假设 2 月 29 日出生的人的生日发生在非闰年的 3 月 1 日。

I am guessing (!) you want to return a result that is equivalent to age expressed in whole years, using the customary rule where the age increases by one on each birthday. This could be calculated using the following template (which you could turn into a function):

<xsl:template name="age-in-years">
    <xsl:param name="start-date"/>
    <xsl:param name="end-date"/>
    
    <xsl:variable name="start-year" select="year-from-date($start-date)"/>
    <xsl:variable name="start-month" select="month-from-date($start-date)"/>
    <xsl:variable name="start-day" select="day-from-date($start-date)"/>
    
    <xsl:variable name="end-year" select="year-from-date($end-date)"/>
    <xsl:variable name="end-month" select="month-from-date($end-date)"/>
    <xsl:variable name="end-day" select="day-from-date($end-date)"/>

    <xsl:value-of select="$end-year - $start-year - number(100 * $end-month + $end-day lt 100 * $start-month + $start-day)" />
</xsl:template> 

Do note that this assumes the birthday of a person born on February 29 occurs on March 1 in a non-leap year.

爱的十字路口 2025-01-22 08:41:27

我自己想出了一个递归解决方案。它不是性能最高的,但它可以工作:

<xsl:function name="d:years-diff">
    <xsl:param name="old.date" as="xs:date"/>
    <xsl:param name="new.date" as="xs:date"/>

    <xsl:variable name="one-year" select="xs:yearMonthDuration('P1Y')"/>

    <xsl:choose>
        <xsl:when test="$old.date + $one-year <= $new.date">
            <xsl:sequence select="$one-year + d:years-diff($old.date + $one-year, $new.date)"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:sequence select="xs:yearMonthDuration('P0Y')"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:function>

您可以使用以下代码验证该功能:

<xsl:template match="/">
    <xsl:text>
One day short of five years:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2002-03-02'), xs:date('2007-03-01'))"/>
    <xsl:text>
Exactly 5 years:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2002-03-02'), xs:date('2007-03-02'))"/>
    <xsl:text>
One day short of one year:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2007-03-02'), xs:date('2006-03-01'))"/>
    <xsl:text>
Exactly one year:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2006-03-02'), xs:date('2007-03-02'))"/>
    <xsl:text>
One year plus one day:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2006-03-02'), xs:date('2007-03-03'))"/>
    <xsl:text>
Same dates:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2007-03-03'), xs:date('2007-03-03'))"/>
</xsl:template>

打印出:

One day short of five years:
P4Y
Exactly 5 years:
P5Y
One day short of one year:
P0M
Exactly one year:
P1Y
One year plus one day:
P1Y
Same dates:
P0M

I figured out a recursive solution by myself. It is not the most performant, but it works:

<xsl:function name="d:years-diff">
    <xsl:param name="old.date" as="xs:date"/>
    <xsl:param name="new.date" as="xs:date"/>

    <xsl:variable name="one-year" select="xs:yearMonthDuration('P1Y')"/>

    <xsl:choose>
        <xsl:when test="$old.date + $one-year <= $new.date">
            <xsl:sequence select="$one-year + d:years-diff($old.date + $one-year, $new.date)"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:sequence select="xs:yearMonthDuration('P0Y')"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:function>

You can verify the function using the following code:

<xsl:template match="/">
    <xsl:text>
One day short of five years:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2002-03-02'), xs:date('2007-03-01'))"/>
    <xsl:text>
Exactly 5 years:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2002-03-02'), xs:date('2007-03-02'))"/>
    <xsl:text>
One day short of one year:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2007-03-02'), xs:date('2006-03-01'))"/>
    <xsl:text>
Exactly one year:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2006-03-02'), xs:date('2007-03-02'))"/>
    <xsl:text>
One year plus one day:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2006-03-02'), xs:date('2007-03-03'))"/>
    <xsl:text>
Same dates:
</xsl:text>
    <xsl:value-of select="d:years-diff(xs:date('2007-03-03'), xs:date('2007-03-03'))"/>
</xsl:template>

which prints out:

One day short of five years:
P4Y
Exactly 5 years:
P5Y
One day short of one year:
P0M
Exactly one year:
P1Y
One year plus one day:
P1Y
Same dates:
P0M
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文