我需要获取两个日期之间的日期列表 - 例如,我有开始日期03302012和结束日期05302012,我需要这样的输出
03302012033120120401201204022012...052820120529201205302012
- 随意使用您的日期格式 - 我将自己进行转换。谢谢!
您可以使用递归模板来执行此操作。这不是最好的解决方案,因为这会受到堆栈溢出或内存不足错误的影响(如果您给它的日期间隔足够大),但它可以是一个开始的地方。
以下示例首先需要的是检查生成的值并确保它是有效日期的方法(您可以在线找到一些示例;我只是使用了来自开源项目的示例,并在示例中导入了该文件,只是为了使其更短)。
然后,这个想法是通过在前一天中添加一天来生成日期,然后在当前日期中添加一天,依此类推。如果当天溢出,则向月份添加一个,然后从第 1 天重新开始。如果月份溢出,则对年份执行相同的操作,并从第 1 个月开始。从理论上讲,唯一永远不会溢出的是年份(但您将使用间隔的结束值来限制它)。
生成日期并对其进行验证。如果它是有效的并且没有达到间隔的终点,你尝试通过添加天数来生成另一个(这就是块 X 中发生的情况)。
当您得到一个无效值时,就会溢出一些东西。它只能是日或月(如上所述)。我首先检查月份(Y块)。如果是这种情况,我从第 1 个月的第 1 天开始,但明年。如果是溢出的那一天(Z块),那么我从下个月的第一天开始。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="http://www.getsymphony.com/download/xslt-utilities/source-code/54294/"/>
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:variable name="startDate" select="'03302012'" /> <!-- MMddyyyy format -->
<xsl:variable name="endDate" select="'05302012'" /> <!-- MMddyyyy format -->
<xsl:template match="/">
<values>
<xsl:call-template name="GenerateList">
<xsl:with-param name="day" select="number(substring($startDate, 3, 2))" />
<xsl:with-param name="month" select="number(substring($startDate, 1, 2))" />
<xsl:with-param name="year" select="number(substring($startDate, 5))" />
</xsl:call-template>
</values>
</xsl:template>
<xsl:template name="GenerateList">
<xsl:param name="day" select="1" />
<xsl:param name="month" select="1" />
<xsl:param name="year" select="1" />
<!-- 1 = valid, 0 = invalid according to the imported file -->
<xsl:variable name="validationResult">
<xsl:call-template name="date-is-valid">
<xsl:with-param name="day" select="$day"/>
<xsl:with-param name="month" select="$month"/>
<xsl:with-param name="year" select="$year"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$validationResult = 0">
<xsl:choose>
<xsl:when test="$month > 12">
<!-- block Y -->
<xsl:call-template name="GenerateList">
<xsl:with-param name="day" select="1" />
<xsl:with-param name="month" select="1" />
<xsl:with-param name="year" select="$year + 1" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- block Z -->
<xsl:call-template name="GenerateList">
<xsl:with-param name="day" select="1" />
<xsl:with-param name="month" select="$month + 1" />
<xsl:with-param name="year" select="$year" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<!-- block X -->
<!-- same MMddyyyy format as the interval values -->
<xsl:variable name="currentDate" select="concat(format-number($month, '00'), format-number($day, '00'), $year)" />
<value>
<xsl:value-of select="$currentDate" />
</value>
<xsl:if test="not($currentDate = $endDate)">
<xsl:call-template name="GenerateList">
<xsl:with-param name="day" select="$day + 1" />
<xsl:with-param name="month" select="$month" />
<xsl:with-param name="year" select="$year" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
不幸的是,XSLT 1.0 本身对于此类任务并不方便,但它的环境通常是。以下是我自己使用的一些方法:
-
最简单的解决方案通常是使这样的列表成为输入的一部分=)
XSLT 转换通常是具有特定 XSLT 处理器的较大应用程序的一部分,该应用程序允许使用特定方法来扩展它。您可以编写一个扩展函数(使用Java,Javascript,PHP,Python,具体取决于处理器),该函数返回所需的节点集。另一个但类似的选择是注册一个"流"(至少在 PHP 方面)并使用带有 url 的函数获取节点集
document
像app://Dates/listdates?start=a&end=b
一样。缺点是样式表与应用程序耦合,不能单独开发。大多数 XSTL 处理器都支持 EXSLT 扩展。您可以使用日期扩展来计算日期之间的天数,使用字符串扩展中的函数生成长度
padding
字符串,将字符串拆分为空字符串以获取标记列表(所需长度),并使用node-set
函数迭代列表并使用date-add
将当前节点位置添加到第一个日期。使用纯 XSLT 和递归模板,如 Bogdan(波格丹)所建议的那样。