XSL 1.0中GMT转本地时间及时间格式修正求助
解决XSLT中转换自定义时间格式到本地时区并正确格式化的问题
首先,咱们得先搞定你给出的原始时间格式21 Dec 2017 03:52:42:000000——它的毫秒部分用冒号分隔,这不符合XSLT标准xs:dateTime的格式要求(标准格式是yyyy-MM-ddThh:mm:ss.sss,毫秒用小数点分隔)。所以第一步要先把这个字符串转换成标准的日期时间类型,之后才能进行时区转换和格式化。
步骤1:将原始时间字符串转换为标准xs:dateTime
你可以用字符串替换函数把最后一个冒号换成小数点,再拆分拼接成标准格式:
<!-- 假设原始时间存储在变量$originalTime中 --> <xsl:variable name="formattedDateTimeStr" select="replace($originalTime, '(\d{2}:\d{2}:\d{2}):(\d{6})', '$1.$2')"/> <xsl:variable name="standardDateTime" select="xs:dateTime( concat( substring($formattedDateTimeStr, 8, 4), '-', <!-- 把月份缩写转成两位数字 --> replace(substring($formattedDateTimeStr, 4, 3), 'Dec', '12') | replace(substring($formattedDateTimeStr, 4, 3), 'Nov', '11') | replace(substring($formattedDateTimeStr, 4, 3), 'Oct', '10') | replace(substring($formattedDateTimeStr, 4, 3), 'Sep', '09') | replace(substring($formattedDateTimeStr, 4, 3), 'Aug', '08') | replace(substring($formattedDateTimeStr, 4, 3), 'Jul', '07') | replace(substring($formattedDateTimeStr, 4, 3), 'Jun', '06') | replace(substring($formattedDateTimeStr, 4, 3), 'May', '05') | replace(substring($formattedDateTimeStr, 4, 3), 'Apr', '04') | replace(substring($formattedDateTimeStr, 4, 3), 'Mar', '03') | replace(substring($formattedDateTimeStr, 4, 3), 'Feb', '02') | replace(substring($formattedDateTimeStr, 4, 3), 'Jan', '01'), '-', substring($formattedDateTimeStr, 1, 2), 'T', substring($formattedDateTimeStr, 12) ) )"/>
这段代码会把21 Dec 2017 03:52:42.000000转换成标准的2017-12-21T03:52:42.000000格式,满足xs:dateTime的类型要求。
步骤2:转换到本地时区
如果你的XSLT版本是2.0及以上,可以直接用adjust-dateTime-to-timezone函数,不传时区参数时默认转换到本地时区:
<xsl:variable name="localDateTime" select="adjust-dateTime-to-timezone($standardDateTime)"/>
要是原始时间本身是UTC时区的,记得指定原始时区参数:
<xsl:variable name="localDateTime" select="adjust-dateTime-to-timezone($standardDateTime, xs:dayTimeDuration('PT0H'))"/>
步骤3:修正格式化参数并输出
你用的'h:mm:ss a'格式本身是对的,但要搭配format-dateTime函数来使用(不能直接用普通的xsl:value-of),确保你的XSLT处理器(比如Saxon)支持这个格式:
<xsl:param name="format" select="'h:mm:ss a'"/> <xsl:value-of select="format-dateTime($localDateTime, $format)"/>
完整示例代码
把所有步骤整合起来的完整代码如下:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl:param name="originalTime" select="'21 Dec 2017 03:52:42:000000'"/> <xsl:param name="format" select="'h:mm:ss a'"/> <xsl:template match="/"> <!-- 转换为带小数点的时间字符串 --> <xsl:variable name="formattedDateTimeStr" select="replace($originalTime, '(\d{2}:\d{2}:\d{2}):(\d{6})', '$1.$2')"/> <!-- 转换为标准xs:dateTime类型 --> <xsl:variable name="standardDateTime" select="xs:dateTime( concat( substring($formattedDateTimeStr, 8, 4), '-', replace(substring($formattedDateTimeStr, 4, 3), 'Dec', '12') | replace(substring($formattedDateTimeStr, 4, 3), 'Nov', '11') | replace(substring($formattedDateTimeStr, 4, 3), 'Oct', '10') | replace(substring($formattedDateTimeStr, 4, 3), 'Sep', '09') | replace(substring($formattedDateTimeStr, 4, 3), 'Aug', '08') | replace(substring($formattedDateTimeStr, 4, 3), 'Jul', '07') | replace(substring($formattedDateTimeStr, 4, 3), 'Jun', '06') | replace(substring($formattedDateTimeStr, 4, 3), 'May', '05') | replace(substring($formattedDateTimeStr, 4, 3), 'Apr', '04') | replace(substring($formattedDateTimeStr, 4, 3), 'Mar', '03') | replace(substring($formattedDateTimeStr, 4, 3), 'Feb', '02') | replace(substring($formattedDateTimeStr, 4, 3), 'Jan', '01'), '-', substring($formattedDateTimeStr, 1, 2), 'T', substring($formattedDateTimeStr, 12) ) )"/> <!-- 转换到本地时区 --> <xsl:variable name="localDateTime" select="adjust-dateTime-to-timezone($standardDateTime)"/> <!-- 格式化输出本地时间 --> <local-time><xsl:value-of select="format-dateTime($localDateTime, $format)"/></local-time> </xsl:template> </xsl:stylesheet>
如果你用的是XSLT 1.0,原生没有时区处理和format-dateTime函数,就得借助EXSLT扩展或者处理器特定的函数来实现,但现在大部分场景都已经在使用XSLT 2.0及以上版本,上面的方案应该能完美解决你的问题。
内容的提问来源于stack exchange,提问作者Ankur Goel
相关产品推荐
相关产品推荐

