技术问询:如何在XSL 1.0中实现装货时间戳减4天的计算
在XSL 1.0中实现日期减4天的解决方案
XSL 1.0确实没有原生的日期计算函数,这算是个常见的痛点了——得手动处理日期的拆解、天数计算和格式重组。针对你的需求,我整理了一套可行的方案,正好适配你给出的YYYY-MM-DD HH:MM:SS格式的日期:
步骤1:提取并拆分日期部分
首先,我们需要从目标节点中提取日期字符串,然后拆分出年、月、日三个部分。因为你的日期格式是固定的YYYY-MM-DD开头,直接用substring函数截取就行:
<!-- 提取原始日期的日期部分(去掉后面的时间) --> <xsl:variable name="raw-date" select="substring(/notify/Blob/xml/TenderOffer/Shipment/ShipmentStop[StopSequence='1']/DepartureTime/EventTime/PlannedTime/GLogDate, 1, 10)" /> <!-- 拆分年、月、日为单独变量 --> <xsl:variable name="year" select="substring($raw-date, 1, 4)" /> <xsl:variable name="month" select="substring($raw-date, 6, 2)" /> <xsl:variable name="day" select="substring($raw-date, 9, 2)" />
步骤2:编写日期计算的自定义模板
接下来要写一个模板处理“减N天”的逻辑,它会自动处理跨月、跨年以及闰年的情况。这里默认设置减4天,你也可以改成参数化的通用模板:
<xsl:template name="subtract-days-from-date"> <xsl:param name="year" /> <xsl:param name="month" /> <xsl:param name="day" /> <xsl:param name="days-to-subtract" select="4" /> <!-- 默认减4天 --> <!-- 定义每个月的天数,2月先按28天算,后面判断闰年调整 --> <xsl:variable name="days-in-month"> <xsl:choose> <xsl:when test="$month = 1 or $month = 3 or $month = 5 or $month = 7 or $month = 8 or $month = 10 or $month = 12">31</xsl:when> <xsl:when test="$month = 4 or $month = 6 or $month = 9 or $month = 11">30</xsl:when> <xsl:when test="$month = 2"> <xsl:choose> <!-- 闰年判断规则:能被4整除但不能被100整除,或者能被400整除 --> <xsl:when test="($year mod 4 = 0 and $year mod 100 != 0) or ($year mod 400 = 0)">29</xsl:when> <xsl:otherwise>28</xsl:otherwise> </xsl:choose> </xsl:when> </xsl:choose> </xsl:variable> <!-- 计算新的日、月、年 --> <xsl:variable name="new-day" select="$day - $days-to-subtract" /> <xsl:choose> <!-- 如果新日期的天数大于0,直接返回当前年月的新日 --> <xsl:when test="$new-day > 0"> <xsl:value-of select="concat($year, '-', format-number($month, '00'), '-', format-number($new-day, '00'))" /> </xsl:when> <!-- 如果新日期的天数小于等于0,需要往前推一个月 --> <xsl:otherwise> <xsl:variable name="prev-month" select="$month - 1" /> <xsl:choose> <!-- 如果当前是1月,往前推到去年的12月 --> <xsl:when test="$prev-month = 0"> <xsl:call-template name="subtract-days-from-date"> <xsl:with-param name="year" select="$year - 1" /> <xsl:with-param name="month" select="12" /> <xsl:with-param name="day" select="31 + $new-day" /> <xsl:with-param name="days-to-subtract" select="0" /> </xsl:call-template> </xsl:when> <!-- 其他月份,取上个月的总天数加上剩余的日数 --> <xsl:otherwise> <xsl:call-template name="subtract-days-from-date"> <xsl:with-param name="year" select="$year" /> <xsl:with-param name="month" select="$prev-month" /> <xsl:with-param name="day" select="$days-in-month + $new-day" /> <xsl:with-param name="days-to-subtract" select="0" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template>
步骤3:调用模板得到结果
最后,在需要展示结果的地方调用这个模板,传入拆分好的年、月、日参数即可:
<!-- 调用模板计算减4天后的日期 --> <xsl:call-template name="subtract-days-from-date"> <xsl:with-param name="year" select="$year" /> <xsl:with-param name="month" select="$month" /> <xsl:with-param name="day" select="$day" /> </xsl:call-template>
测试你的示例
针对你给出的2022-05-19 14:57:00这个日期:
- 拆分得到年=2022,月=05,日=19
- 减去4天后,日=19-4=15,大于0,直接返回
2022-05-15,完全符合你的需求。
如果遇到跨月的情况(比如2022-03-02减4天),模板会自动计算为2022-02-26;闰年的情况也能正确处理(比如2020-03-01减2天得到2020-02-28)。
内容的提问来源于stack exchange,提问作者bjorn.delaat




