当减去今天的日期时,给出正确的输出.
select
(TRUNC(to_date('25/05/2016','dd/mm/yyyy'))-TRUNC(to_date('02/01/2016','dd/mm/yyyy')))
from dual;
Run Code Online (Sandbox Code Playgroud)
输出:144天
当今天采取日期时,下面的广告sysdate应该给144.但是显示其他一些值?为什么?
select
(to_date(SYSDATE,'dd/mm/yyyy'))-(to_date('02/01/2016','dd/mm/yyyy'))
from dual;
Run Code Online (Sandbox Code Playgroud)
输出:-730343(显示一些值).
当你这样做时:
to_date(SYSDATE,'dd/mm/yyyy')
Run Code Online (Sandbox Code Playgroud)
您使用NLS_DATE_FORMAT将SYSDATE(已经是日期)隐式转换为字符串.从似乎是DD-MON-RR的结果.所以你真的在做:
to_date(to_char(SYSDATE,'DD-MON-RR'),'dd/mm/yyyy')
Run Code Online (Sandbox Code Playgroud)
内部部分为您提供字符串'25 -MAY-16'.当你将它转换回带yyyy掩码的日期时,你有一个两位数的年份,16,这被解释为0016年而不是2016年.如果你用的话,你实际上会得到你所期望的rrrr,但这是一个愉快的副作用,它仍会在不同NLS设置的会话中中断:
select to_date(SYSDATE,'dd/mm/yyyy') as bad_nls,
to_char(to_date(SYSDATE,'dd/mm/yyyy'), 'YYYY-MM-DD') as bad_string,
to_date(SYSDATE,'dd/mm/rrrr') as ok_nls,
to_char(to_date(SYSDATE,'dd/mm/rrrr'), 'YYYY-MM-DD') as ok_string
from dual;
BAD_NLS BAD_STRING OK_NLS OK_STRING
--------- ---------- --------- ----------
25-MAY-16 0016-05-25 25-MAY-16 2016-05-25
Run Code Online (Sandbox Code Playgroud)
请注意,使用当前的NLS掩码和隐式转换为字符串,您无法区分第一个和第三个结果; 但显而易见的是,在第二和第四个结果中以四位数年份显示出来是错误的.
通过隐式转换,您将0016-05-25与2016-01-02进行比较,并且它给出了-730343,因为它是2000年中的天数,根据您预期的差距144天进行了调整.
正如Praveen已经说过你不需要to_date()用于SYSDATE,如果你试图将时间部分设置为午夜,你可以截断它.
select date '2016-05-25' - date '2016-01-02' as diff1,
date '2016-05-25' - date '0016-05-25' as diff2,
date '0016-05-25' - date '2016-01-02' as diff3,
trunc(sysdate) - date '2016-01-02' as diff4
from dual;
DIFF1 DIFF2 DIFF3 DIFF4
---------- ---------- ---------- ----------
144 730487 -730343 144
Run Code Online (Sandbox Code Playgroud)
但更一般地说,不要使用两位数年份(唉,似乎我们已经忘记了Y2K的教训!),并且不依赖于NLS设置.