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时会出现完全相同的问题。)
有谁知道是否
分享并享受。
根据菲尔的回答,这些问题仍然发生在11.2。
Cthulhu fhtagn。
10.2.0.4中的相同错误
答案 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)