Oracle 11.1错误将Julian日期编号转换为DATE或TIMESTAMP

时间:2012-05-03 12:52:57

标签: oracle oracle11g

This recent post让我忙着调查Oracle中的Julian日期转换,我发现了我认为是Oracle 11.1中的一个错误。测试用例是:

案例1。

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

这应该按照定义的here返回“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”(关闭一天不到一年)。< / p>

案例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?
  3. 分享并享受。


    根据菲尔的回答,这些问题仍然发生在11.2。

    Cthulhu fhtagn。


    10.2.0.4中的相同错误

3 个答案:

答案 0 :(得分:2)

当试图了解Oracle应该做什么时,请查看Oracle的documentation,“朱利安日数是自公元前4712年1月1日以来的天数。”

该措辞确实意味着Julian 1将是自公元前4712年1月1日起的一天,换句话说是1月2日。但是,Julian日期计算的当前实施已经存在了很长时间,现有代码依赖于关于行为。 (我知道如果在Oracle中实现的Julian定义要改变,我们就会被搞砸了。)此时,自从公元前4713年12月31日以来,它最多只是一个文档错误。

编辑reference找到{1}},其中Julian 1是1月1日。不是普通的数据库程序员会看到的。

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

  

Oracle数据库使用计算朱利安的天文系统   天,公元前4713年被指定为-4712。历史   相比之下,计算朱利安天的系统指定为公元前4713年   -4713。如果您将Oracle Julian天数与使用历史系统计算的值进行比较,请注意允许365天   BC日期的差异。有关更多信息,请参阅   Call Interface Programmer's Guide

案例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 :(得分: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 > 

答案 2 :(得分:0)