XSLT日期时间格式

时间:2017-07-27 03:45:46

标签: xslt xslt-2.0

如果我有以下内容:

<showtime><time>2017-01-01T15:30:01.331Z</time><time>2017-01-02T20:30:00.995Z</time></showtime>

有没有办法使用xslt格式化日期时间,以便它可以在毫秒内完成并将最后一部分更改为仅2位数?

结果:

<showtime><time>2017-01-01T15:30:01.33Z</time><time>2017-01-02T20:30:01.00Z</time></showtime>

4 个答案:

答案 0 :(得分:1)

正如其他人所说,XSLT 2.0中的format-dateTime基本上可以满足您的需求。不幸的是,在处理秒和毫秒时存在一些粗糙的边缘。有两个单独的图片元素用于格式化秒和小数秒。原则上'[s01],[f001]'将秒的两位数字和小数秒的三位数字组成,用逗号分隔。但是复杂性出现了像23.9999这样的值。

XSLT 2.0说:“在小数秒组件的情况下,该值四舍五入到指定的大小,就好像通过应用函数round-half-to-even(fractional-seconds,max-width)。”无论如何解释它,这并没有给出将.9999的小数秒值舍入到三位数的合理答案。没有提到将任何溢出滚动到秒值(并且可能然后进入分钟值,小时值等)。

在函数和操作符3.1规范中,使用阻力最小的路径修复了此错误:规范被更改为表示该值被截断为指定的宽度。

如果以2016-12-31T23:59:59.9999Z四舍五入到2017-01-01T00:00:00.00这样的方式实现舍入非常重要,那么你将不得不写逻辑自己。

答案 1 :(得分:0)

如果截断是可以接受的并且不需要真正的舍入,这个简单的解决方案适用于XSLT 1.0和2.0:

<xsl:template match="showtime/time">
  <xsl:copy>
    <xsl:value-of select="concat(substring(., 1, 22), 'Z')"/>
  </xsl:copy>
</xsl:template>

答案 2 :(得分:0)

XSLT 2 中,您可以使用 format-date format-dateTime format-time

不幸的是,这些函数分别采用 xs:date xs:dateTime xs:time 值(不仅仅是字符串)。 因此,首先必须选择相应的日期/时间子串 (来自源内容)并创建这些日期/时间变量。

然后,您可以使用 picture 参数指定的任何格式输出这些值。

答案 3 :(得分:0)

令人惊讶的是,尽管XPath 2.0提供了所有日期/时间功能,但这项任务有多么困难和尴尬。

无论如何,这就是我提出的。请注意,这是通过两个独立且独立的步骤完成的:首先我们计算舍入的dateTime值,然后我们对其进行格式化。与其他人所说的不同,格式化在这里是微不足道的部分。

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="time">
    <xsl:variable name="seconds" select="3600 * hours-from-dateTime(.) + 60 * minutes-from-dateTime(.) + seconds-from-dateTime(.)" />
    <xsl:variable name="round-seconds" select="round($seconds * 100) div 100" />

    <xsl:variable name="dur" select="xs:dayTimeDuration(concat('PT', $seconds, 'S'))" />
    <xsl:variable name="round-dur" select="xs:dayTimeDuration(concat('PT', $round-seconds, 'S'))" />

    <xsl:variable name="new-dateTime" select="xs:dateTime(.) - $dur + $round-dur" />
    <xsl:copy>
        <xsl:value-of select="format-dateTime($new-dateTime, '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01].[f01][ZN]')" /> 
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>