JD Edwards / IBM iSeries DB2儒略日期/日历日期SQL转换

lh80um4z  于 2022-11-07  发布在  DB2
关注(0)|答案(3)|浏览(180)

在IBM iSeries上运行的上个世纪遗留下来的应用程序仍在使用中,例如JD Edwards。日期字段通常以各种格式存储,统称为Julian Date。这些格式是年和年中日期的组合,现在更准确地称为**Ordinal Date**。
JD Edwards ERP应用程序数据库中广泛使用的一种特定儒略日期格式是6位数格式(YYDDD),由3位数年份(表示为自1900年以来的年数)和3位数日期(带前导零)组成。

在SQL中拥有一种在这两种格式之间进行转换的清晰简洁的方法非常有用。
下面是IBM为Converting Julian Dates to Calendar Dates提供的一个解决方案:

Select date (days(concat(cast(integer(1900000+"SDIVD") /1000 as Char(4)),'-01-01'))+mod(integer(1900000+" SDIVD"),1000)-1)

哎哟,头好痛......
我希望有一种更简单、更容易的方法可以只使用IBM iSeries DB2 SQL语法来转换这两种方式。

u0sqgete

u0sqgete1#

我不确定您使用什么来显示数据,但是
1940年至2039年(含)
与会话设置相关联,不应返回NULL,而应返回通常由'++++++++'表示的计算错误。NULL通常由一个短划线'-'表示。如果更改会话设置以ISO格式而不是MDY格式显示日期,超出范围的日期应该正常显示。2有关String representations of datetime values的IBM文章。3我不知道为什么这个设置甚至会影响像DAYOFYEAR这样的标量函数,但它确实会影响。4(编辑:在向IBM提交错误报告后,他们发布了PTF,以解决DAYOFYEAR SI 77129(7.3)和SI 77130(7.4)的这一特定问题)
我能跑

SELECT DATE(CHAR(140001 + 1900000)) FROM sysibm.sysdummy1;

并且得到了

2040-01-01

为了将日期转换为长朱利安,然后转换为序数日期,我找到了一个更短的版本:

SELECT INT(TO_CHAR('2019-10-18','YYYYDDD'))-1900000 FROM sysibm.sysdummy1;
332nm8kg

332nm8kg2#

对于IBM i Db2(7.2版),我已经确定了以下两种在儒略日期和日历日期之间进行转换的方法:

-- Julian to Db2 Date (Method 1.0)
DATE(CAST(120050 + 1900000 AS CHAR(7)))

-- Db2 Date to Julian (Method 2.0)
1000 * (YEAR(DATE('02/19/2020')) - 1900) + DAYOFYEAR(DATE('02/19/2020'))

更新.我发现第一种方法可以缩短为:

-- Julian to Db2 Date (Method 1.1)
DATE(CHAR(120050 + 1900000))

下面是在SQL语句中使用它们的一些示例(沿着IBM的方法):

SELECT
    TEST_DATA."DATE"
    , TEST_DATA."JULIAN"
    , YEAR(TEST_DATA."DATE") AS "YEAR"
    , DAYOFYEAR(TEST_DATA."DATE") AS "DAYOFYEAR"
    , DATE(DAYS(CONCAT(CAST(INTEGER(1900000 + TEST_DATA."JULIAN") / 1000 AS CHAR(4)), '-01-01')) + MOD(INTEGER(1900000 + TEST_DATA."JULIAN"), 1000) - 1) AS "METHOD_IBM"
    , DATE(CAST((TEST_DATA."JULIAN" + 1900000) AS CHAR(7))) AS "METHOD_1.0"
    , DATE(CHAR(TEST_DATA."JULIAN" + 1900000)) AS "METHOD_1.1"
    , 1000 * (YEAR(TEST_DATA."DATE") - 1900) + DAYOFYEAR(TEST_DATA."DATE") AS "METHOD_2.0"
FROM
    TABLE
    (
        VALUES
              (DATE('12/31/1938'), 039365)
            , (DATE('12/31/1939'), 039365)
            , (DATE('01/01/1940'), 040001)
            , (DATE('02/19/2020'), 120050)
            , (DATE('2020-01-01'), 119366)
            , (DATE('2039-01-01'), 139001)
            , (DATE('2039-12-31'), 139365)
            , (DATE('2040-01-01'), 140001)
            , (DATE('2041-01-15'), 141015)
    )
    AS TEST_DATA("DATE", "JULIAN")
;

突出显示的记录由另一个答案提示:
尝试IBM的版本和您的119366版本...
我不知道是否有一个“标准”来说明这个特定的值,但我会说119366不是一个有效的儒略日期,因为2019年不是闰年,只有365天。我认为允许“溢出”到后续年份是一个不利的方法,我也没有见过任何遗留应用程序以这种方式存储日期。一般来说,我希望我的查询突出显示数据中的不规则性,而不是屏蔽它们。
请注意,至少有一些数据库标量函数只计算1940年到2039年之间的日期(包括1940年和2039年)。我已经包括了这个范围之外的一些日期,以演示奇怪的行为。我不确定IBM在哪里记录了这种行为,但documentation for the scalar DAYOFYEAR function中没有提到。

2uluyalo

2uluyalo3#

尝试IBM的版本和您的119366版本...
无论您选择哪种转换方法,我都会将其 Package 在用户定义函数(UDF)中。
这样做可以实现自定义错误处理,例如,对于存储日期的数字字段,所有的零可能意味着“未设置”,可以替换为空,而所有的9应该替换为9999-12-31。
使用UDF意味着您可以考虑使用不同的语言来进行转换,例如RPG。
另一个要考虑的选择是“日期”/“日历”/“日期维”表。非常方便,不仅仅是日期转换。谷歌搜索会找到很多适用于任何数据库的信息。
有关IBM i的特定示例,请查看红皮书IBM DB2 Web Query for i: The Nuts and Bolts的第5章(注意,如果您碰巧安装了Db2 for i Web Query,则有一个脚本可以创建这样的日期表。)
例如,日期维度数据表可能包含下列数据行:

  • Julian传统日期,在联接到使用Julian传统日期的文件时使用
  • 压缩的十进制(8,0)旧日期,在联接到使用压缩的十进制(8,0)旧日期的文件时使用
  • 字符(8)继承日期,在联接到使用字符(8)继承日期的文件时使用
  • 日期(真正的DB2日期字段)
  • 会计年度-会计季度
  • 星期几(星期一、星期二等)
  • 一年中的月份(一月、二月等)
  • 季节(春、夏、秋、冬)
  • 去年(一周)的同一天
  • 周结束日期
  • 一年中的第几周
  • 超级碗周日旗帜(Y或N)
  • 假日前一天标志(Y或N)
  • 假日标志的第二天(Y或N)
  • 满月旗(Y或N)

相关问题