将 JDE 儒略日期 (CYYDDD) 转换为 XSLT 或 SQL 中的 YYYY-MM-DD 格式
Convert a JDE Julian Date (CYYDDD) to YYYY-MM-DD format in XSLT or SQL
我有一个条件需要将 JDE Julian 日期 (CYYDDD
) 转换为 XSLT 中的 YYYY-MM-DD
格式。任何人都可以帮助解决一些 SQL 查询或任何其他我们可以做到的方式 XSLT。
非常感谢您的帮助。
提前致谢。
这是一个很好的帮助,但是为 MS Excel 编写的。您可以将其转换为 SQL 或您喜欢的任何其他内容:Converting a Julian Date
这也可能有帮助:Julian Calendar Help
这里有几个处理 JDE Julian 日期(不同于 Julian 日期的官方定义)的解决方案。对于 JDE:
- 单位,数字的十位和百位部分是指自年初以来的天数;
'001'
对应 1st January
.
- 千位以上都对应年份;
100
代表年份 2000
.
- 示例:
100001
是 2000-01-01
以下两种解决方案的工作方式相同:
- 日期除以 1000 & 结果四舍五入(向下舍入)得到数字的年份部分(即去掉最后 3 位数字)。例如
123321
=> 123
.
- 加上 1900 就得到了实际的年份。例如
123 + 1900
=> 2023
- 然后我们通过构建 1 月 1 日的日期字符串并将该字符串转换为日期,将其转换为有效日期;例如
2023
-> 2023-01-01
.
- 日期模数 1000 returns 日期偏移了数字的一部分(即基本上切断了除最后 3 位以外的所有数字)。例如
123321
=> 321
.
- 我们从天数偏移中取 1(即因为
1st Jan
是 001
;而不是 000
)。例如321
=> 320
- 然后,我们将从年部分计算的 1 月 1 日日期偏移天部分的天数。例如
2023-01-01 + 320 days
=> 2023-11-17
MS SQL
create function dbo.ConvertJulianToDate (
@JulianDate integer
)
returns date
begin
return dateadd(
day
, @JulianDate % 1000 - 1
,cast(
cast(
@JulianDate / 1000 + 1900
as varchar(4)
) + '-01-01'
as date
)
)
end
示例用法
select dbo.ConvertJulianToDate(117175)
XSLT 2.0
<xsl:template name="JulianToDate">
<xsl:param name="JulianDate" select="./text()" />
<xsl:variable name="year" select="1900 + floor(($JulianDate div 1000))" />
<xsl:variable name="days" select="($JulianDate mod 1000) - 1" />
<xsl:value-of select="xs:date(concat($year,'-01-01')) + xs:dayTimeDuration(concat('P',$days,'D'))"/>
</xsl:template>
完整代码
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="xsl xs fn"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/*">
<Root>
<CallOnCurrentElement>
<xsl:call-template name="JulianToDate" />
</CallOnCurrentElement>
<PassValue>
<xsl:call-template name="JulianToDate">
<xsl:with-param name="JulianDate">114026</xsl:with-param>
</xsl:call-template>
</PassValue>
</Root>
</xsl:template>
<xsl:template name="JulianToDate">
<xsl:param name="JulianDate" select="./text()" />
<xsl:variable name="year" select="1900 + floor(($JulianDate div 1000))" />
<xsl:variable name="days" select="($JulianDate mod 1000) - 1" />
<xsl:value-of select="xs:date(concat($year,'-01-01')) + xs:dayTimeDuration(concat('P',$days,'D'))"/>
</xsl:template>
</xsl:transform>
样本XML
<?xml version="1.0" encoding="UTF-8"?>
<julianDate>117175</julianDate>
Fiddle 演示:http://xsltransform.net/6pS1zCU
XSLT 1.0
日期函数在 XSLT 1.0 中不可用,因此它非常 hacky。但是我相信这应该有效。
<xsl:template name="JulianToDate">
<xsl:param name="JulianDate" select="./text()" />
<xsl:variable name="year" select="1900 + floor(($JulianDate div 1000))" />
<xsl:variable name="days" select="($JulianDate mod 1000)" />
<xsl:variable name="isLeapYear" select="(($year mod 4) = 0) and ((($year mod 100) != 0) or (($year mod 400) = 0))" />
<xsl:variable name="month" select="1" />
<xsl:variable name="day" select="1" />
<xsl:variable name="febDays">
<xsl:choose>
<xsl:when test="$isLeapYear">29</xsl:when>
<xsl:otherwise>28</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="31 >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days" />
<xsl:with-param name="MM" select="1" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(31 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days -31" />
<xsl:with-param name="MM" select="2" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(63 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (31 + $febDays)" />
<xsl:with-param name="MM" select="3" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(92 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (63 + $febDays)" />
<xsl:with-param name="MM" select="4" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(123 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (92 + $febDays)" />
<xsl:with-param name="MM" select="5" />
<xsl:with-param name="yyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(153 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (123 + $febDays)" />
<xsl:with-param name="MM" select="6" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(184 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (153 + $febDays)" />
<xsl:with-param name="MM" select="7" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(215 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (184 + $febDays)" />
<xsl:with-param name="MM" select="8" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(245 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (215 + $febDays)" />
<xsl:with-param name="MM" select="9" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(276 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (245 + $febDays)" />
<xsl:with-param name="MM" select="10" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(306 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (276 + $febDays)" />
<xsl:with-param name="MM" select="11" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(337 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (306 + $febDays)" />
<xsl:with-param name="MM" select="12" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">Invalid Julian Date</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="CreateDate">
<xsl:param name="yyyy" />
<xsl:param name="MM" />
<xsl:param name="dd" />
<xsl:value-of select="concat(substring(10000 + $yyyy, 2),'-',substring(100 + $MM, 2),'-',substring(100 + $dd, 2))"/>
</xsl:template>
(这只是替换了 XSLT 2.0 版本中的等效模板;所有其他内容(版本号除外)应该相同。
我有一个条件需要将 JDE Julian 日期 (CYYDDD
) 转换为 XSLT 中的 YYYY-MM-DD
格式。任何人都可以帮助解决一些 SQL 查询或任何其他我们可以做到的方式 XSLT。
非常感谢您的帮助。 提前致谢。
这是一个很好的帮助,但是为 MS Excel 编写的。您可以将其转换为 SQL 或您喜欢的任何其他内容:Converting a Julian Date
这也可能有帮助:Julian Calendar Help
这里有几个处理 JDE Julian 日期(不同于 Julian 日期的官方定义)的解决方案。对于 JDE:
- 单位,数字的十位和百位部分是指自年初以来的天数;
'001'
对应1st January
. - 千位以上都对应年份;
100
代表年份2000
. - 示例:
100001
是2000-01-01
以下两种解决方案的工作方式相同:
- 日期除以 1000 & 结果四舍五入(向下舍入)得到数字的年份部分(即去掉最后 3 位数字)。例如
123321
=>123
. - 加上 1900 就得到了实际的年份。例如
123 + 1900
=>2023
- 然后我们通过构建 1 月 1 日的日期字符串并将该字符串转换为日期,将其转换为有效日期;例如
2023
->2023-01-01
. - 日期模数 1000 returns 日期偏移了数字的一部分(即基本上切断了除最后 3 位以外的所有数字)。例如
123321
=>321
. - 我们从天数偏移中取 1(即因为
1st Jan
是001
;而不是000
)。例如321
=>320
- 然后,我们将从年部分计算的 1 月 1 日日期偏移天部分的天数。例如
2023-01-01 + 320 days
=>2023-11-17
MS SQL
create function dbo.ConvertJulianToDate (
@JulianDate integer
)
returns date
begin
return dateadd(
day
, @JulianDate % 1000 - 1
,cast(
cast(
@JulianDate / 1000 + 1900
as varchar(4)
) + '-01-01'
as date
)
)
end
示例用法
select dbo.ConvertJulianToDate(117175)
XSLT 2.0
<xsl:template name="JulianToDate">
<xsl:param name="JulianDate" select="./text()" />
<xsl:variable name="year" select="1900 + floor(($JulianDate div 1000))" />
<xsl:variable name="days" select="($JulianDate mod 1000) - 1" />
<xsl:value-of select="xs:date(concat($year,'-01-01')) + xs:dayTimeDuration(concat('P',$days,'D'))"/>
</xsl:template>
完整代码
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
exclude-result-prefixes="xsl xs fn"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/*">
<Root>
<CallOnCurrentElement>
<xsl:call-template name="JulianToDate" />
</CallOnCurrentElement>
<PassValue>
<xsl:call-template name="JulianToDate">
<xsl:with-param name="JulianDate">114026</xsl:with-param>
</xsl:call-template>
</PassValue>
</Root>
</xsl:template>
<xsl:template name="JulianToDate">
<xsl:param name="JulianDate" select="./text()" />
<xsl:variable name="year" select="1900 + floor(($JulianDate div 1000))" />
<xsl:variable name="days" select="($JulianDate mod 1000) - 1" />
<xsl:value-of select="xs:date(concat($year,'-01-01')) + xs:dayTimeDuration(concat('P',$days,'D'))"/>
</xsl:template>
</xsl:transform>
样本XML
<?xml version="1.0" encoding="UTF-8"?>
<julianDate>117175</julianDate>
Fiddle 演示:http://xsltransform.net/6pS1zCU
XSLT 1.0
日期函数在 XSLT 1.0 中不可用,因此它非常 hacky。但是我相信这应该有效。
<xsl:template name="JulianToDate">
<xsl:param name="JulianDate" select="./text()" />
<xsl:variable name="year" select="1900 + floor(($JulianDate div 1000))" />
<xsl:variable name="days" select="($JulianDate mod 1000)" />
<xsl:variable name="isLeapYear" select="(($year mod 4) = 0) and ((($year mod 100) != 0) or (($year mod 400) = 0))" />
<xsl:variable name="month" select="1" />
<xsl:variable name="day" select="1" />
<xsl:variable name="febDays">
<xsl:choose>
<xsl:when test="$isLeapYear">29</xsl:when>
<xsl:otherwise>28</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="31 >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days" />
<xsl:with-param name="MM" select="1" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(31 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days -31" />
<xsl:with-param name="MM" select="2" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(63 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (31 + $febDays)" />
<xsl:with-param name="MM" select="3" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(92 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (63 + $febDays)" />
<xsl:with-param name="MM" select="4" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(123 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (92 + $febDays)" />
<xsl:with-param name="MM" select="5" />
<xsl:with-param name="yyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(153 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (123 + $febDays)" />
<xsl:with-param name="MM" select="6" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(184 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (153 + $febDays)" />
<xsl:with-param name="MM" select="7" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(215 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (184 + $febDays)" />
<xsl:with-param name="MM" select="8" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(245 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (215 + $febDays)" />
<xsl:with-param name="MM" select="9" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(276 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (245 + $febDays)" />
<xsl:with-param name="MM" select="10" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(306 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (276 + $febDays)" />
<xsl:with-param name="MM" select="11" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:when test="(337 + $febDays) >= $days">
<xsl:call-template name="CreateDate">
<xsl:with-param name="dd" select="$days - (306 + $febDays)" />
<xsl:with-param name="MM" select="12" />
<xsl:with-param name="yyyy" select="$year" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">Invalid Julian Date</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="CreateDate">
<xsl:param name="yyyy" />
<xsl:param name="MM" />
<xsl:param name="dd" />
<xsl:value-of select="concat(substring(10000 + $yyyy, 2),'-',substring(100 + $MM, 2),'-',substring(100 + $dd, 2))"/>
</xsl:template>
(这只是替换了 XSLT 2.0 版本中的等效模板;所有其他内容(版本号除外)应该相同。