xml xslt xpath xslt-1.0 xslt-2.0

xml - Encontrar la diferencia entre dos dateTimes en XSLT



xpath xslt-1.0 (4)

Tengo un archivo XML que incluye algunas fechas con puntos de inicio y finalización, como se muestra a continuación:

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

Pregunta:

¿Cómo calcular la diferencia entre dos atributos de tiempo?


Recibo el error: ... xsl:version: only 1.0 features are supported

Aquí hay una solución puramente 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>

Demostración: http://xsltransform.net/jz1PuNG/1


Verifiqué y descubrí que puedo usar XSLT versión 2. También por horas / fechas me refería a diferentes fechas, lo que significa cuántos días, horas, minutos y segundos.

Entonces te sugiero que lo hagas siguiendo las líneas de:

<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>

Demo completa: http://xsltransform.net/jz1PuNG


Sus fechas están en formato ISO, así que en XSLT 2.0 puede hacer

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

El resultado es un xs:dayTimeDuration , que puede convertir a segundos (por ejemplo) haciendo

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


Utilizando Saxon procesador Saxon compatible con XSLT3.0, uso esto (también debería funcionar para 2.0): - xs es el esquema 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)))"/>