Преобразование даты JDE по юлианскому календарю (CYYDDD) в формат YYYY-MM-DD в XSLT или SQL

У меня есть условие, когда мне нужно преобразовать дату JDE по юлианскому календарю (CYYDDD) в формат YYYY-MM-DD в XSLT. Может ли кто-нибудь помочь с каким-либо SQL-запросом или любым другим способом, которым мы можем сделать это XSLT.

Я действительно ценю твою помощь. Заранее спасибо.


person Gnaneshwar    schedule 24.06.2017    source источник
comment
Опубликуйте пример вашего ввода и ожидаемого результата. Я очень сомневаюсь, что это юлианская дата. Кто использует юлианские даты в базе данных? Возможно, это номер дня по юлианскому календарю? Также укажите, можете ли вы использовать XSLT 2.0.   -  person michael.hor257k    schedule 24.06.2017
comment
Привет, Майкл, мы интегрируем JDE в стороннюю службу, поэтому у нас есть юлианская дата в таблицах JDE, и нам нужно преобразовать эту дату и отправить ее в стороннюю службу в формате ГГГГ-ММ-ДД. ниже информация. Юлина Дата: 117175 и результат: 24.06.2017. Заранее спасибо..!   -  person Gnaneshwar    schedule 24.06.2017
comment
Вот один для JDE EnterpriseOne в SQL (как отмечено в вашем посте); изменит для XSLT перед публикацией в качестве ответа: gist.githubusercontent.com/JohnLBevan/65eda22a8550c8c26b6b   -  person JohnLBevan    schedule 24.06.2017
comment
@Gnaneshwar 1. У вас есть не юлианская дата, а дата в формате CYYDDD. Некоторые люди называют это датой Дж. Д. Эдвардса по юлианскому календарю, но, как я понимаю, без веской причины. 2. Вы так и не сказали, поддерживает ли ваш процессор XSLT 2.0.   -  person michael.hor257k    schedule 24.06.2017
comment
@ michael.hor257k К вашему сведению: сами JDEdwards назвали этот формат даты юлианской датой, поэтому любой, кто работает с JDE, назвал бы его так. Так что, хотя это и не юлианская дата в самом строгом смысле, это правильный термин.   -  person JohnLBevan    schedule 24.06.2017
comment
@JohnLBevan Я не работаю с JDE, и компания JD Edwards не является авторитетом в терминологии дат. Термин дата по юлианскому календарю взят.   -  person michael.hor257k    schedule 24.06.2017


Ответы (2)


Вот несколько решений для работы с юлианскими датами JDE (которые отличаются от официального определения юлианской даты). Для JDE:

  • Единицы, десятки и сотни в числе относятся к дням с начала года; где '001' соответствует 1st January.
  • Все в тысячах и выше соответствует году; где 100 представляет год 2000.
  • Пример: 100001 равно 2000-01-01

Оба приведенных ниже решения работают одинаково:

  • Дата, деленная на 1000, и полученный результат (округленный в меньшую сторону) дает часть года числа (т. е. отбрасывает последние 3 цифры). например 123321 => 123.
  • Добавление 1900 к этому дает нам фактический год. например 123 + 1900 => 2023
  • Затем мы преобразуем это в действительную дату, создав строку даты для 1 января и преобразовав строку в дату; например 2023 -> 2023-01-01.
  • Модуль даты 1000 возвращает часть числа со смещением дней (т. е. по существу отсекает все, кроме последних 3 цифр). например 123321 => 321.
  • Мы берем 1 из смещения дней (т. е. потому что 1st Jan равно 001, а не 000). например 321 => 320
  • Затем мы смещаем нашу дату 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, так что это очень сложно. Однако я считаю, что это должно сработать.

    <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; все остальное (кроме номера версии) должно быть идентичным.

person JohnLBevan    schedule 24.06.2017
comment
Спасибо, Джон. выглядит великолепно. Небольшой вопрос, не могли бы вы сообщить мне, почему у нас есть ‹PassValue›, который показывает другую дату. но ‹CallOnCurrentElement› показывает точную дату ввода. Я действительно ценю твою помощь. Заранее спасибо..!! - person Gnaneshwar; 24.06.2017
comment
PassValue просто еще одна демонстрация. Для этого я определил значение в файле XSL, а не в XML. Чисто для демонстрационных целей. - person JohnLBevan; 25.06.2017
comment
Любой, кто хочет развлечься, связанный с юлианскими датами, может прочитать этот пост: /a> или эта книга: goodreads.com/book/show/39074550- скромный пи - person JohnLBevan; 26.06.2019

Вот хороший хелп, но написанный для MS Excel. Вы можете преобразовать его в SQL или во что угодно другое: Преобразование юлианской даты

Это также может помочь: Справка по юлианскому календарю

person Ali Hashemi    schedule 24.06.2017
comment
Спасибо за помощь Али. Я пробовал это, но не работал в XSLT. - person Gnaneshwar; 24.06.2017
comment
@Gnaneshwar Опубликуйте свою попытку, чтобы мы могли ее исправить, вместо того, чтобы писать для вас код с нуля. - person michael.hor257k; 24.06.2017
comment
Я подозреваю, что он использует xslt 1.0, даты jd edwards обычно можно найти в веб-приложениях, таких как Peoplesoft. - person Paulb; 24.06.2017