Reputation: 21
When subtracting today's date like below gives correct output.
select
(TRUNC(to_date('25/05/2016','dd/mm/yyyy'))-TRUNC(to_date('02/01/2016','dd/mm/yyyy')))
from dual;
output : 144 days
When taking todays date ad sysdate below should give 144. but shows some other value? Why?
select
(to_date(SYSDATE,'dd/mm/yyyy'))-(to_date('02/01/2016','dd/mm/yyyy'))
from dual;
output: -730343 (shows some value).
Upvotes: 1
Views: 216
Reputation: 191570
When you do:
to_date(SYSDATE,'dd/mm/yyyy')
you're implicitly converting SYSDATE, which is already a date, to a string - using your NLS_DATE_FORMAT. From the result that seems to be DD-MON-RR. So you're really doing:
to_date(to_char(SYSDATE,'DD-MON-RR'),'dd/mm/yyyy')
The inner part gives you the string '25-MAY-16'. When you convert that back to a date with the yyyy
mask you have a two-digit year, 16, which is interpreted as year 0016 rather than 2016. You'd actually get what you expect if you used rrrr
instead, but that's a happy side effect, and it'll still break in session with different NLS settings:
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
Notice that with your current NLS mask and the implicit conversion to a string you can't tell the difference between the first and third result; but it's obvious that it's wrong when shown with a four-digit year in the second and fourth results.
With your implicit conversion you're comparing 0016-05-25 with 2016-01-02, and it is giving you -730343 as that's how many days there are in 2000 years, adjusted for the 144 days you expected the gap to be.
As Praveen already said you don't need to use to_date()
for SYSDATE, and if you're trying to set the time portion to midnight you can just truncate it.
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
More generally, though, don't use two-digit years (alas it seems we've already forgotten the lessons of Y2K!), and don't rely on NLS settings.
Upvotes: 5
Reputation: 9365
You don't need to convert a date
[sysdate
] to date
using to_date
Use trunc
to strip the time portion of the sysdate
.
Try;
select
TRUNC(SYSDATE) - (to_date('02/01/2016','dd/mm/yyyy'))
from dual;
Upvotes: 1