Oracle 11.1 将儒略日数转换为 DATE 或 TIMESTAMP 的错误

问题描述 投票:0回答:3

最近的这篇文章让我忙于调查 Oracle 中的儒略日期转换,并且我发现了我认为是 Oracle 11.1 中的一个错误。测试用例是:

案例1.

SELECT TO_CHAR(TO_TIMESTAMP('0', 'J'), 'DD MON SYYYY') FROM DUAL

这应该返回“01 JAN -4713”,如此处所定义,但会引发错误

ORA-01854: julian date must be between 1 and 5373484

案例2.

SELECT TO_CHAR(TO_TIMESTAMP('1', 'J'), 'DD MON SYYYY') FROM DUAL

这应该返回“02 JAN -4713”作为上述内容的扩展(比儒略零日期晚一天),但返回“01 JAN -4712”(相差不到一年的一天)。

案例3.

SELECT TO_CHAR(TO_TIMESTAMP('1721424', 'J'), 'DD MON SYYYY') FROM DUAL

返回“01 JAN 0001”。没关系(就目前而言)。如果我们从上面的日期值中减去 1,我们期望它返回前一天,即 31 DEC -0001(零年不存在);但是,当我们执行以下命令时

SELECT TO_CHAR(TO_TIMESTAMP('1721423', 'J'), 'DD MON SYYYY') FROM DUAL

抛出以下错误:

ORA-01841: (full) year must be between -4713 and +9999, and not be 0

表明 Oracle 已尝试生成零年份。

(请注意,虽然上面的测试用例中使用了 TO_TIMESTAMP,但使用 TO_DATE 时也会出现完全相同的问题)。

有谁知道吗

  1. Oracle 已记录这些问题?
  2. 11.2还存在这些问题吗?

分享并享受。


根据下面 Phil 的回答,这些问题在 11.2 中仍然出现。

克苏鲁 fhtagn。


10.2.0.4 中的相同错误

oracle oracle11g
3个回答
2
投票

当尝试了解 Oracle 应该做什么时,请查看 Oracle 的文档,“儒略日数是自公元前 4712 年 1 月 1 日以来的天数。”

该措辞确实暗示儒略日 1 是自公元前 4712 年 1 月 1 日以来的一天,换句话说,1 月 2 日。然而,儒略日期计算的当前实现已经存在很长时间了,现有代码取决于行为。 (我知道,如果 Oracle 中实现的 Julian 定义发生变化,我们就会完蛋。)此时,自公元前 4713 年 12 月 31 日以来最多只是一个文档错误。

编辑调用接口程序员指南中找到了Julian 1为1月1日的参考。不是普通数据库程序员会看的地方。

以下解释维基百科和Oracle之间的年份差异:

Oracle数据库使用计算儒略的天文系统 天,其中公元前 4713 年被指定为 -4712。历史的 相反,计算儒略日的系统将 4713 BC 指定为 -4713。如果您将 Oracle 儒略日与使用历史系统计算的值进行比较,请注意考虑 365 天 BC 日期的差异。有关更多信息,请参阅 http://www.usno.navy.mil/USNO/astronomical-applications/astronomical-information-center/millennium.

案例 3 对我来说是新闻。谢谢你提出来。我不知道有任何涉及该行为的参考资料。相关:

SQL> select to_date('0001-01-01', 'YYYY-MM-DD') 
    - to_date ('-0001-12-31', 'SYYYY-MM-DD') from dual;

TO_DATE('0001-01-01','YYYY-MM-DD')-TO_DATE('-0001-12-31','SYYYY-MM-DD')
-----------------------------------------------------------------------
                                                                    367

SQL> select months_between(to_date('0001-01-01', 'YYYY-MM-DD')
  2      , to_date ('-0001-12-31', 'SYYYY-MM-DD')) from dual;

MONTHS_BETWEEN(TO_DATE('0001-01-01','YYYY-MM-DD'),TO_DATE('-0001-12-31','SYYYY-MM-DD'))
---------------------------------------------------------------------------------------
                                                                             12.0322581

显然不存在的0年是闰年。


1
投票

这是在 11.2.0.1.0 上执行的相同查询:

PHIL@PHILL11G2 > select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0  Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

Elapsed: 00:00:00.04
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('0', 'J'), 'DD MON SYYYY') FROM DUAL;
SELECT TO_CHAR(TO_TIMESTAMP('0', 'J'), 'DD MON SYYYY') FROM DUAL
                            *
ERROR at line 1:
ORA-01854: julian date must be between 1 and 5373484


Elapsed: 00:00:00.00
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('1', 'J'), 'DD MON SYYYY') FROM DUAL;

TO_CHAR(TO_T
------------
01 JAN -4712

Elapsed: 00:00:00.00
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('1721424', 'J'), 'DD MON SYYYY') FROM DUAL;

TO_CHAR(TO_T
------------
01 JAN  0001

Elapsed: 00:00:00.00
PHIL@PHILL11G2 > SELECT TO_CHAR(TO_TIMESTAMP('1721423', 'J'), 'DD MON SYYYY') FROM DUAL;
SELECT TO_CHAR(TO_TIMESTAMP('1721423', 'J'), 'DD MON SYYYY') FROM DUAL
                            *
ERROR at line 1:
ORA-01841: (full) year must be between -4713 and +9999, and not be 0


Elapsed: 00:00:00.04
PHIL@PHILL11G2 > 

© www.soinside.com 2019 - 2024. All rights reserved.