【问题标题】:Finding the difference between two dateTimes in XSLT在 XSLT 中查找两个日期时间之间的差异
【发布时间】:2016-11-30 23:01:59
【问题描述】:

我有一个XML 文件,其中包含一些带有起点和终点的日期,如下所示:

<start time="2016-02-21T00:59:06+02:00"/>
.....
.....
<end time="2016-02-22T02:24:38+02:00"/>

问题:

如何计算两个时间属性之间的差异?

【问题讨论】:

  • 对于 XSLT1,您可能想看看 EXSLT date:difference。有关使用 EXSLT,请参阅this StackOverflow answer
  • @halfbit ,但您可能知道无法下载所需的软件包。
  • 你能使用 XSLT 2.0 吗?
  • @TimC 我想是的。
  • 我能说什么...你注意到我说过“我建议你确定一下,因为它在这里有很大的不同”吗?

标签: xml xslt xpath xslt-1.0 xslt-2.0


【解决方案1】:

我收到错误消息:...xsl:version: only 1.0 features are supported

这是一个纯粹的 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>

演示:http://xsltfiddle.liberty-development.net/aiyndK

【讨论】:

  • 天哪,为什么这个答案不是首先出现在谷歌搜索 XSLT 日期差异时。非常感谢伙计。我要到处复制这个链接!
  • 我知道这是一个旧线程,但我正在尝试这种方法并发现奇怪的结果。当开始时间为偶数小时,结束时间为 30 分钟后,它始终显示持续时间为 7 小时。如果开始时间是 30 分钟,结束时间是偶数小时,我会得到 -6 小时的持续时间。我也有类似的异常,持续时间为 1.5 小时 45 分钟。
  • 无法重现您声明的结果:xsltfiddle.liberty-development.net/6r5Gh3o
【解决方案2】:

您的日期是 ISO 格式,所以在 XSLT 2.0 中您可以这样做

xs:dateTime(end/@time) - xs:dateTime(start/@time)

结果是xs:dayTimeDuration,您可以通过执行将其转换为秒(例如)

(xs:dateTime(end/@time) - xs:dateTime(start/@time)) div xs:dayTimeDuration('PT1S')

【讨论】:

    【解决方案3】:

    我检查并发现我可以使用 XSLT 版本 2。 时间/日期我的意思是日期不同,这意味着多少天, 小时、分钟和秒。

    那么我建议你按照以下方式进行:

    <xsl:variable name="duration" select="xs:dateTime(end/@time) - xs:dateTime(start/@time)" />
    <xsl:value-of select="days-from-duration($duration)"/>
    <xsl:text> days, </xsl:text>
    <xsl:value-of select="hours-from-duration($duration)"/>
    <xsl:text> hours, </xsl:text>
    <xsl:value-of select="minutes-from-duration($duration)"/>
    <xsl:text> minutes and </xsl:text>
    <xsl:value-of select="seconds-from-duration($duration)"/>
    <xsl:text> seconds</xsl:text>
    

    完整演示:http://xsltfiddle.liberty-development.net/aiyndK/1

    【讨论】:

      【解决方案4】:

      使用符合 XSLT3.0 的 Saxon 处理器,我使用这个(也应该适用于 2.0):- xs 是 xsd 架构

      <xsl:variable name="to" select="...to node value"/>
      <xsl:variable name="from" select"...from node value"/>
      <xsl:value-of select="days-from-duration(xs:dayTimeDuration(xs:date($to) - xs:date($from)))"/>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-29
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多