Oracle: TO_DATE can not parse result of TO_CHAR [duplicate] - oracle

This question already has an answer here:
TO_DATE function time zone parse error
(1 answer)
Closed 4 years ago.
I try to parse a time-string on a Oracle 12. Problem is the TZH I think.
SQL> select to_char(current_timestamp, 'DD.MM.YYYY HH24:MI TZH') from dual;
TO_CHAR(CURRENT_TIME
--------------------
05.07.2018 16:55 +02
But it is not working the other direction...
SQL> select TO_DATE('05.07.2018 16:53 +02', 'DD.MM.YYYY HH24:MI TZH') from dual;
select TO_DATE('05.07.2018 16:53 +02', 'DD.MM.YYYY HH24:MI TZH') from dual
*
FEHLER in Zeile 1:
ORA-01821: Datumsformat nicht erkannt
It does not like the format. Also not working if I remove the +.

As was mentioned in the comments, TO_DATE does not work with a time zone format mask. Instead, use TO_TIMESTAMP_TZ, which does accept this:
SELECT TO_TIMESTAMP_TZ('05.07.2018 16:53 +02:00', 'DD.MM.YYYY HH24:MI TZH:TZM')
FROM dual;
Demo
It's not surprising that this is a source of confusion, because much of the documentation I saw online for TO_DATE mentions the TZH and TZM format masks, despite that they crash the function if used.

Related

How to convert DATETIME in specific format to DATE in PL/SQL

I apologize for asking a simple question, but I could not find the answer on the forum.
I need to convert from this datetime '2009-06-18T00:00:00+06:00' to format 'YYYY-MM-DD' in PL/SQL.
If this "datetime" is really a timestamp (as it looks like), not a string, then you can choose how to display it (using TO_CHAR) or convert to DATE (using TO_DATE), or simply TRUNCATE it. Note that the last two results (i.e. the way they are displayed) depend on current NLS settings (set by my ALTER SESSION).
Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test
2 as (select to_timestamp_tz ('2009-06-18T00:00:00+06:00',
3 'yyyy-mm-dd"t"hh24:mi:ss tzh:tzm')
4 col
5 from dual)
6 select to_char (col, 'yyyy-mm-dd') res1,
7 to_date (to_char (col, 'yyyy-mm-dd'), 'yyyy-mm-dd') res2,
8 trunc (col) res3
9 from test;
RES1 RES2 RES3
---------- ---------- ----------
2009-06-18 18.06.2009 18.06.2009
SQL>
Use TO_DATE on the first 10 characters in your timestamp string:
SELECT TO_DATE(SUBSTR('2009-06-18T00:00:00+06:00', 1, 10), 'YYYY-MM-DD') FROM dual
Demo
Documentation is the best part.
http://www.sqlines.com/oracle-to-sql-server/to_date
you can use the TO_DATE(string, format) function for that so it will be like
SELECT TO_DATE('2012-06-05', 'YYYY-MM-DD') FROM xyz;
DEPENDS on the data type.
If the column is DATE data type, then, as suggested already, TRUNC would do the job to display. But, if your locale-specific NLS date settings are different, then you will still see the time portion as midnight.
Else, you need to use TO_DATE with proper FORMAT and apply TRUNC to it.
update
If you only want to display, use TO_CHAR, else, if you have a filter in your WHERE clause, then remember TO_CHAR doesn't return DATE, it converts it into literal.

to_date function with sysdate

select TO_CHAR(to_date(sysdate, 'DD-MON-YYYY'), 'DAY') FROM DUAL;
When I run this query the output was : SUNDAY. But we know today is Tuesday(1-1-2013).
And
then changed the query as
select TO_CHAR(to_date('01-JAN-2013', 'DD-MON-YYYY'), 'DAY') FROM DUAL;
answer was :TUESDAY.
then Changed query as
select TO_CHAR(to_date(sysdate+1, 'DD-MON-YYYY'), 'DAY') FROM DUAL;
answer is :MONDAY.
When I using the sysdate why it is show SUNDAY as output?
I am new in oracle db. Please help me.
use this:
select TO_CHAR(sysdate, 'DAY') FROM DUAL;
you are using this :
to_date(sysdate, 'DD-MON-YYYY')
which is giving you date=1/1/0013 which is sunday
Please refer the documentation for sysdate here. Sysdate is already a date data type.
Your example query is inappropriate as to_date function takes first parameter as String not date.
Try the simple query below:
select TO_CHAR(sysdate, 'DAY') FROM DUAL;
This should return TUESDAY as output.
To_date is used to convert a strin to date. As sysdate is already a date, one must not add add to_date.

What does hh23 mean on oracle

I read a lot of tutorial which uses hh23 and hh24 interchangeably. to do to_char on oracle. Is the hh23 a legacy syntax? I tried doing it on simple query and it causes an error.
select to_char(sysdate, 'hh23'), to_char(sysdate, 'hh24') from dual
I'm trying to find a reference to this but there is none. Or is the tutorial just written wrong? For example on http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:59412348055.
I think it's just a typo.
SQL> select to_char(sysdate, 'hh23:mi:ss') from dual
2 /
select to_char(sysdate, 'hh23:mi:ss') from dual
*
ERROR at line 1:
ORA-01821: date format not recognized
SQL> select to_char(sysdate, 'hh24:mi:ss') from dual
2 /
TO_CHAR(
--------
11:25:21
SQL>
It is just a typing error in untested code. 'hh23' will always give an error.

Date function on oracle

I've got a question about date function on oracle.
I have the following table
statistic_table(
pages AS varchar(10),
date_created AS date
);
I have the following sql
SELECT COUNT(*) FROM statistic_table WHERE date_created BETWEEN sysdate-5 AND sysdate-1
and
SELECT COUNT(*) FROM statistic_table WHERE date_created BETWEEN to_date('12-AUG-2011') AND to_date('16-AUG-2011');
the question is, why is it return different numbers. assuming sysdate-5 returns 12-aug-2011 and sysdate-1 returns 16-aug-2011
Any help would be much appreciated!
Cheers,
sysdate - 5 will give you a date with the current time. So if I ran it at 1pm precisely, the query would be equivalent to:
select (*)
FROM statistic_table
WHERE date_created BETWEEN to_date('12-Aug-2011 13:00:00')
AND to_date('16-Aug-2011 13:00:00')
whereas the second query is:
select (*)
FROM statistic_table
WHERE date_created BETWEEN to_date('12-Aug-2011 00:00:00')
AND to_date('16-Aug-2011 00:00:00')
you should probably try this instead:
select (*)
FROM statistic_table
WHERE date_created BETWEEN trunc(sysdate) -5
AND trunc(sysdate) -1
A date in Oracle is a point in time with a precision of a second.
SYSDATE returns the current date and time and is therefore not the same as to_date('17-AUG-2011'):
SQL> SELECT to_char(sysdate, 'dd-mon-yyyy hh24:mi:ss') FROM DUAL;
TO_CHAR(SYSDATE,'DD-MON-YYYYHH
------------------------------
17-aug-2011 15:52:13
Use the TRUNC function if you only want the date component:
SQL> SELECT to_char(trunc(sysdate), 'dd-mon-yyyy hh24:mi:ss') FROM DUAL;
TO_CHAR(TRUNC(SYSDATE),'DD-MON
------------------------------
17-aou-2011 00:00:00
Because SYSDATE includes a time component, so if the current time is 11:22:33, then
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN sysdate-5 AND sysdate-1
is actually equivalent to
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN to_date('12-AUG-2011 11:22:33','DD-MON-YYYY HH24:MI:SS')
AND to_date('16-AUG-2011 11:22:33','DD-MON-YYYY HH24:MI:SS')
To avoid the time component do this:
SELECT COUNT(*) FROM statistic_table
WHERE date_created BETWEEN TRUNC(sysdate)-5 AND TRUNC(sysdate)-1
An Oracle DATE always has a day and a time component.
sysdate-5 returns a date exactly 5 days ago. If today is August 17 at 10 AM, for example, sysdate-5 returns August 12 at 10 AM.
to_date('12-AUG-2011', 'DD-MON-YYYY'), on the other hand, returns August 12 at midnight. So it returns a date that is 10 hours earlier than sysdate-5.
sysdate auto returns with a time component as mentioned by the previous answers.
When using to_date it is converting a string to a date. With this being said you can pass in parameters to make it return the same thing.
Have a look at this link that explains it.
to_date parameters

Oracle date format problem

I have the following strange problem in Oracle
(Please keep in mind that I have little experience in SQL and even less in Oracle).
If I do this:
SELECT TO_CHAR(sysdate, 'YYYY-MM-DD HH24:MI') FROM dual
I get this:
2010-12-02 18:39
All fine there.
However, if I do this:
UPDATE favorite_item
SET favorite_item.last_used_date = TO_DATE(sysdate, 'YYYY-MM-DD HH24:MI')
WHERE favorite_item.favorite_item_id = 1
I get this in my database:
10-DEC-02
Which is the 10th of December '02 which is not correct
If I do this to confirm:
SELECT TO_CHAR(favorite_item.last_used_date, 'YYYY-MM-DD HH24:MI') AS last_used_date
FROM favorite_item
WHERE favorite_item.favorite_item_id = 1
I get this:
0002-12-10 00:00
Which is completely wrong.
What am I doing wrong? I feel that the date setting is not working correctly.
Thanks in advance for your help.
Don't use TO_DATE() on sysdate; sysdate is already a date.
UPDATE favorite_item
SET favorite_item.last_used_date = sysdate
WHERE favorite_item.favorite_item_id = 1`
The problem is using the to_date() function on anything other than a string.
As to why you are getting the wrong results, there is an internal conversion that happens when you use to_date on a date. Since to_date actually takes input as a string, your date is initially converted into a string (according to your NLS_DATE_FORMAT setting) and then converted back to a date. Hence the mismatch.
SQL> select sysdate from dual;
SYSDATE
---------
02-DEC-10
SQL> select to_date(sysdate,'YYYY-MM-DD') from dual;
TO_DATE(S
---------
10-DEC-02
--- This is because, the above string is actually executed as
SQL> select to_date(
to_char('02-DEC-10','YYYY-MM-DD') from dual;
TO_DATE('
---------
10-DEC-02
SQL> select to_date(
2 /* implicit conversion... dd-mon-yy' is my session's NLS_DATE_FORMAT */
3 to_char(sysdate,'dd-mon-yy'),
4 'YYYY-MM-DD')
5 from dual;
TO_DATE(/
---------
10-DEC-02
sysdate returns a date, so converting it to a date using to_date(sysdate, ...) is redundant/not necessary. You're getting that odd result because the date is being cast to a string by the to_date function using the Oracle default of "DD-MON-YY" and then back into a date using your supplied format, "YYYY-MM-DD". Since the formats don't match, Oracle is interpreting the year as the day and the day as the year. This works correctly (but, again, is redundant):
select to_date(sysdate, 'DD-MON-YY') from dual;

Resources