【问题标题】:Convert a JDE Julian Date (CYYDDD) to YYYY-MM-DD format in XSLT or SQL在 XSLT 或 SQL 中将 JDE 儒略日期 (CYYDDD) 转换为 YYYY-MM-DD 格式
【发布时间】:2017-11-27 18:55:40
【问题描述】:

我需要在 XSLT 中将 JDE Julian Date (CYYDDD) 转换为 YYYY-MM-DD 格式。任何人都可以帮助一些 SQL 查询或任何其他我们可以做到的方式 XSLT。

非常感谢您的帮助。 提前致谢。

【问题讨论】:

  • 发布您的输入和预期输出的示例。我非常怀疑这是一个“朱利安约会”。谁在数据库中使用儒略日期?也许这是一个儒略日数?还要说明您是否可以使用 XSLT 2.0。
  • 嗨,Micheal,我们正在将 JDE 集成到第三方服务中,因此我们在 JDE 表中有朱利安日期,我们需要转换该日期并将其以 YYYY-MM-DD 格式发送到第三方服务。以下是信息。 JulinaDate:117175,结果:2017-06-24。提前谢谢..!
  • 这是用于 SQL 中 JDE EnterpriseOne 的一个(如您的帖子所标记的);在作为答案发布之前将修改 XSLT:gist.githubusercontent.com/JohnLBevan/65eda22a8550c8c26b6b
  • @Gnaneshwar 1. 您拥有的不是儒略日期,而是CYYDDD 格式的日期。有些人称其为 JD Edwards Julian 约会,我看不出有什么好的理由。 2. 你仍然没有说你的处理器是否支持 XSLT 2.0。
  • @JohnLBevan 我不与 JDE 合作,JD Edwards 公司不是日期术语的权威。 朱利安日期这个词被采用了。

标签: sql datetime xslt soa julian-date


【解决方案1】:

这里有一些处理 JDE 儒略日期的解决方案(与官方定义的儒略日期不同)。对于 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 返回数字的天数偏移部分(即,除了最后 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>

小提琴演示: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 版本中的等效模板;所有其他(版本号除外)都应该相同。

【讨论】:

  • 谢谢约翰。它看起来很棒。一个简单的问题,请让我知道为什么我们有显示不同日期的 。但 显示输入的确切日期。我真的很感谢你的帮助。提前谢谢..!!
  • PassValue 只是另一个演示。为此,我在 XSL 文件中而不是在 XML 中定义了值。纯粹是为了演示目的。
  • 任何想要与朱利安约会相关的娱乐的人都可以阅读这篇文章:twitter.com/Tesco/status/1143449559722594306,或这本书:goodreads.com/book/show/39074550-humble-pi
【解决方案2】:

这是一个很好的帮助,但是是为 MS Excel 编写的。您可以将其转换为 SQL 或您喜欢的任何其他内容:Converting a Julian Date

这也可能有帮助:Julian Calendar Help

【讨论】:

  • 感谢阿里的帮助。我试过这个,但不能在 XSLT 中工作。
  • @Gnaneshwar 发布您的尝试,以便我们修复它,而不必从头开始为您编写代码。
  • 我怀疑他使用的是 xslt 1.0,jd edwards 日期通常在 Peoplesoft 等网络应用中找到
猜你喜欢
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
相关资源
最近更新 更多