【问题标题】:XSLT 1.0 Date Duration (Years)XSLT 1.0 日期持续时间(年)
【发布时间】:2020-07-23 23:46:09
【问题描述】:

我正在使用 XSLT 1.0 输出两个日期字段之间的持续时间。以下代码(来自https://stackoverflow.com/a/38615456/3016153)按预期输出以天、小时、分钟和秒为单位的持续时间,但我还需要将其更新为输出年份。有没有人对我如何更新此代码以输出年份持续时间有任何建议?也欢迎替代代码,但它必须使用 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:strip-space elements="*"/>

<xsl:template match="event">
<xsl:variable name="start">
    <xsl:call-template name="dateTime-to-seconds">
        <xsl:with-param name="dateTime" select="start/@time" />
    </xsl:call-template>
</xsl:variable> 

<xsl:variable name="end">
    <xsl:call-template name="dateTime-to-seconds">
        <xsl:with-param name="dateTime" select="end/@time" />
    </xsl:call-template>
</xsl:variable>

<xsl:variable name="duration" select="$end - $start" />
<xsl:variable name="d" select="floor($duration div 86400)"/>
<xsl:variable name="t" select="$duration mod 86400"/>
<xsl:variable name="h" select="floor($t div 3600)"/>
<xsl:variable name="r" select="$t mod 3600"/>
<xsl:variable name="m" select="floor($r div 60)"/>
<xsl:variable name="s" select="$r mod 60"/>
<xsl:copy>
    <xsl:copy-of select="name"/>
    <duration>
        <xsl:value-of select="$d"/>
        <xsl:text> days, </xsl:text>
        <xsl:value-of select="$h"/>
        <xsl:text> hours, </xsl:text>
        <xsl:value-of select="$m"/>
        <xsl:text> minutes and </xsl:text>
        <xsl:value-of select="$s"/>
        <xsl:text> seconds</xsl:text>
    </duration>
    </xsl:copy>
   </xsl:template>

   <xsl:template name="dateTime-to-seconds">
  <xsl:param name="dateTime"/>

<xsl:variable name="date" select="substring-before($dateTime, 'T')" />
<xsl:variable name="time" select="substring-after($dateTime, 'T')" />

<xsl:variable name="local-time" select="substring($time, 1, string-length($time) - 6)" />
<xsl:variable name="offset" select="substring-after($time, $local-time)" />

<xsl:variable name="year" select="substring($date, 1, 4)" />
<xsl:variable name="month" select="substring($date, 6, 2)" />
<xsl:variable name="day" select="substring($date, 9, 2)" />

<xsl:variable name="hour" select="substring($local-time, 1, 2)" />
<xsl:variable name="minute" select="substring($local-time, 4, 2)" />
<xsl:variable name="second" select="substring($local-time, 7)" />

<xsl:variable name="offset-sign" select="1 - 2 * starts-with($offset, '-')" />
<xsl:variable name="offset-hour" select="substring($offset, 2, 2) * $offset-sign" />
<xsl:variable name="offset-minute" select="substring($offset, 5, 2) * $offset-sign" />

<xsl:variable name="a" select="floor((14 - $month) div 12)"/>
<xsl:variable name="y" select="$year + 4800 - $a"/>
<xsl:variable name="m" select="$month + 12*$a - 3"/>    
<xsl:variable name="jd" select="$day + floor((153*$m + 2) div 5) + 365*$y + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045" />

 <xsl:value-of select="86400*$jd + 3600*$hour + 60*$minute + $second - 3600*$offset-hour - 60*$offset-minute" />


 </xsl:template> 

 </xsl:stylesheet>

示例 XML:

<events>
<event>
    <name>Alpha</name>
    <start time="2015-02-21T00:59:06+02:00"/>
    <end time="2018-02-22T02:24:38+02:00"/>
</event>
<event>
    <name>Bravo</name>
    <start time="2016-02-21T00:59:06+02:00"/>
    <end time="2020-03-05T02:24:38+02:00"/>
</event>
<event>
    <name>Charlie</name>
    <start time="2016-02-21T00:59:06+02:00"/>
    <end time="2020-02-21T00:59:06+01:00"/>
</event>
在这里输入代码

【问题讨论】:

  • 这个问题没有正确答案,因为一年中的天数不同。您需要对一年是什么做出一些假设..
  • 嗨@michael.hor257k,您能否提供更多关于需要做出哪些类型的假设的详细信息?
  • 你可以做出任何你想要的假设。例如,您可以假设每 365 天构成一年。或者在开始日期的“周年纪念日”过去一年。或任何其他符合您以这种格式提供信息的目的的假设。关键是您需要在构建计算之前做出 一些 假设。并且任何计算只有在这个假设下才是“正确的”,而不是另一个。
  • @michael.hor257k 感谢您的澄清。如果我们假设每 365 天构成一年,是否可以更新代码以输出一年?
  • 如果您假设,您需要做的就是将年份计算为floor($d div 365),将天数计算为$d mod 365。但是你需要计算到秒精度的差异,却愿意接受app的错误,这似乎有点奇怪。每 4 年 1 天。

标签: xslt xslt-1.0


【解决方案1】:

如 cmets 所述,如果您愿意假设每 365 天构成一年,那么您需要做的就是更改这部分:

<duration>
    <xsl:value-of select="$d"/>
    <xsl:text> days, </xsl:text>
    <xsl:value-of select="$h"/>
    <xsl:text> hours, </xsl:text>
    <xsl:value-of select="$m"/>
    <xsl:text> minutes and </xsl:text>
    <xsl:value-of select="$s"/>
    <xsl:text> seconds</xsl:text>
</duration>

到:

<duration>
    <xsl:value-of select="floor($d div 365)"/>
    <xsl:text> years, </xsl:text>
    <xsl:value-of select="$d mod 365"/>
    <xsl:text> days, </xsl:text>
    <xsl:value-of select="$h"/>
    <xsl:text> hours, </xsl:text>
    <xsl:value-of select="$m"/>
    <xsl:text> minutes and </xsl:text>
    <xsl:value-of select="$s"/>
    <xsl:text> seconds</xsl:text>
</duration>

正如 cmets 中所述,在计算到秒精度的计算中,您愿意接受大约每 4 年 1 天的误差是相当奇怪的。如果您只需要天的精度,那么您应该通过移除计算小时、分钟和秒的部分来节省处理器时间和电力。

【讨论】:

    猜你喜欢
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2017-09-01
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    相关资源
    最近更新 更多