Seconds to Time in XSLT

2019-01-20 14:22发布

问题:

I'm not asking a question actually. I signed up stackoverflow to give something back to a community that has helped me so many times.

If you are using XSLT 1.0 there are no built-in time calculations. I came up with this to convert seconds into minutes and hours. I hope this helps someone!

<xsl:template name="format-duration">
  <xsl:param name="value" />

  <xsl:variable name="minutes" select="floor($value div 60) mod 60" />
  <xsl:variable name="seconds" select="$value mod 60" />
  <xsl:variable name="hours" select="floor($value div 3600)" />


  <xsl:if test="$hours">
    <xsl:if test="$hours &lt; 10">
      <xsl:text>0</xsl:text>
    </xsl:if>
    <xsl:value-of select="$hours" />

    <xsl:text>:</xsl:text>
  </xsl:if>


  <xsl:if test="$minutes">
    <xsl:if test="$minutes &lt; 10">
      <xsl:text>0</xsl:text>
    </xsl:if>
    <xsl:value-of select="$minutes" />
    <xsl:text></xsl:text>
  </xsl:if>

  <xsl:if test="$minutes and $seconds">
    <xsl:text>:</xsl:text>
  </xsl:if>

  <xsl:if test="$seconds">
    <xsl:value-of select="$seconds" />
    <xsl:text></xsl:text>
  </xsl:if>
</xsl:template>

EDIT: Do you have any other methods to achieve the same?

回答1:

Firt of all, thank you for your contribution. There are, however, a few issues with this implementation. The seconds output doesn't take the leading 0 into account, but even if that's fixed, the output can be ambiguous if any of the figures happens to be 0. For example, the inputs 36005, 605, and 36300 all produce the result 10:05.

Likewise if two of the figures happen to be zero. The input 36000 produces the output 10:, and the inputs 600 and 10 both produce the result 10.

Here is how I would go about implementing this functionality:

  <xsl:template name="format-duration">
    <xsl:param name="value" select="." />
    <xsl:param name="alwaysIncludeHours" select="false()" />
    <xsl:param name="includeSeconds" select="true()" />

    <xsl:if test="$value > 3600 or $alwaysIncludeHours">
      <xsl:value-of select="concat(format-number($value div 3600, '00'), ':')"/>
    </xsl:if>

    <xsl:value-of select="format-number(floor($value div 60) mod 60, '00')" />

    <xsl:if test="$includeSeconds">
      <xsl:value-of select="concat(':', format-number($value mod 60, '00'))" />
    </xsl:if>
  </xsl:template>

This way, hours are only displayed if they are non-zero or optionally turned on, and seconds are included by default, but can be optionally omitted by using the parameter values. This should reduce the ambiguity about what a time is supposed to represent.

It also allows omitting the value parameter if the value you want to format is the current context node.



回答2:

Converting number of seconds to time (HH:MM:SS) in XSLT 1.0:

<xsl:template name="seconds-to-time">
    <xsl:param name="seconds"/>
    <xsl:variable name="h" select="floor($seconds div 3600)"/>
    <xsl:variable name="m" select="floor($seconds div 60) mod 60"/>
    <xsl:variable name="s" select="$seconds mod 60"/>

    <xsl:value-of select="format-number($h, '00')" />
    <xsl:value-of select="format-number($m, ':00')" />
    <xsl:value-of select="format-number($s, ':00')" />
</xsl:template>