Converting a date in oracle - oracle

I need to convert one date in different formats:
Below is the example-
There is one field named as APRVL_DT and lets take 3 values of this column are
APRVL_DT
18-JUN-12 09.25.34.000000000 AM
02-JUL-12 09.46.42.000000000 AM
16-JAN-14 09.54.26.000000000 AM
not sure about the timezone.It may be UTC.
Now i want to convert this fields in the format where i'll get data according to daylight saving.So Output should be
New_APRVL_DT
18-JUN-12 01.25.34.000000000 PM
02-JUL-12 01.46.42.000000000 PM
16-JAN-14 02.54.26.000000000 PM
I written one code which is giving me data but not in daylightsaving format-
TO_CHAR(FROM_TZ (TO_TIMESTAMP (APRVL_DT , 'YYYY-MM-DD HH:MI:SS'), 'EST5EDT') AT TIME ZONE 'UTC', 'YYYY-MM-DD HH:MI:SS A.M.') As NEW_APRVL_DT
Please help me in this.

You seem to want to convert a string representing a plain timestamp that you know represents an EST/EDT time to UTC (though the description in the question and your conversion attempt contradict each other). You really should not be storing dates or timestamps as strings, but if that is what you are stuck with, you just need to convert to (and from) the right data type. So you can do:
select APRVL_DT,
TO_CHAR(
SYS_EXTRACT_UTC(
FROM_TZ(TO_TIMESTAMP(APRVL_DT, 'DD-MON-RR HH:MI:SS.FF AM'), 'America/New_York')
), 'DD-MON-RR HH:MI:SS.FF AM') AS NEW_APRVL_DT
from your_table
APRVL_DT NEW_APRVL_DT
------------------------------- -------------------------------
18-JUN-12 09.25.34.000000000 AM 18-JUN-12 01:25:34.000000000 PM
02-JUL-12 09.46.42.000000000 AM 02-JUL-12 01:46:42.000000000 PM
16-JAN-14 09.54.26.000000000 AM 16-JAN-14 02:54:26.000000000 PM
db<>fiddle
Although that is essentially what your attempt was already doing...
If your session date language doesn't, or might not, match the language used for the month abbreviations in your table then you can specify that in the query:
select APRVL_DT,
TO_CHAR(
SYS_EXTRACT_UTC(
FROM_TZ(TO_TIMESTAMP(APRVL_DT, 'DD-MON-RR HH:MI:SS.FF AM', 'NLS_DATE_LANGUAGE=ENGLISH'), 'America/New_York')
), 'DD-MON-RR HH:MI:SS.FF AM', 'NLS_DATE_LANGUAGE=ENGLISH') AS NEW_APRVL_DT
from your_table
db<>fiddle

There is one field named as APRVL_DT [...] not sure about the timezone. It may be UTC.
Now i want to convert this fields in the format where i'll get data according to daylight saving.
You have the time zones in the wrong order:
SELECT APRVL_DT,
FROM_TZ( APRVL_DT, 'UTC' ) AT TIME ZONE 'EST5EDT' As NEW_APRVL_DT
FROM table_name
Which, for the sample data:
CREATE TABLE table_name ( aprvl_dt TIMESTAMP );
INSERT INTO table_name ( aprvl_dt )
SELECT TIMESTAMP '2012-06-18 09:25:34.000000000' FROM DUAL UNION ALL
SELECT TIMESTAMP '2012-06-02 09:46:42.000000000' FROM DUAL UNION ALL
SELECT TIMESTAMP '2014-01-16 09:54:26.000000000' FROM DUAL;
Outputs:
APRVL_DT | NEW_APRVL_DT
:---------------------------- | :--------------------------------
2012-06-18 09:25:34.000000000 | 2012-06-18 05:25:34.000000000 EDT
2012-06-02 09:46:42.000000000 | 2012-06-02 05:46:42.000000000 EDT
2014-01-16 09:54:26.000000000 | 2014-01-16 04:54:26.000000000 EST
From this comment:
APRVL_DT has EST timezone.
SELECT APRVL_DT,
FROM_TZ( APRVL_DT, 'EST' ) AT TIME ZONE 'EST5EDT' As NEW_APRVL_DT
FROM table_name
Which outputs:
APRVL_DT | NEW_APRVL_DT
:---------------------------- | :--------------------------------
2012-06-18 09:25:34.000000000 | 2012-06-18 10:25:34.000000000 EDT
2012-06-02 09:46:42.000000000 | 2012-06-02 10:46:42.000000000 EDT
2014-01-16 09:54:26.000000000 | 2014-01-16 09:54:26.000000000 EST
db<>fiddle here

Related

VARCHAR2 to TIMESTAMP conversion in ORACLE 12c

I have a column in table A as
select create_time from table_a;
The value is
08-MAR-19 08.23.47.897000000 PM GMT.
This column has been marked as VARCHAR2 for some business purpose. Now I am trying to get this column and convert the value to TIMESTAMP for some purpose, like this as below:
SELECT TO_TIMESTAMP(create_time, 'DD-MON-YYYY HH.MI.SS.FF AM') from table_a;
But I am getting error:
ORA-01830: date format picture ends before converting entire input string
Can someone help me to convert this varchar data to timestamp. The reason I am trying to do is, I need to convert this time from one timezone to another :
eg:
SELECT FROM_TZ(TO_TIMESTAMP(create_time, 'DD-MON-YYYY HH.MI.SS.FF AM'), 'UTC') AT TIME ZONE 'CET' from table_a;
SQL> select replace('08-MAR-19 08.23.47.897000000 PM GMT','GMT','') AS RESULT from dual
;
RESULT
--------------------------------
08-MAR-19 08.23.47.897000000 PM
SQL> select to_timestamp(replace('08-MAR-19 08.23.47.897000000 PM GMT','GMT','')) as RESULT from dual ;
RESULT
---------------------------------------------------------------------------
08-MAR-19 08.23.47.897000000 PM
SQL> select from_tz(to_timestamp(replace('08-MAR-19 08.23.47.897000000 PM GMT','GMT','')),'UTC') AT TIME ZONE 'CET' AS RESULT from dual ;
RESULT
---------------------------------------------------------------------------
08-MAR-19 09.23.47.897000000 PM CET
SQL>
The four characters GMT at the end are not accounted for in your format string
SELECT TO_TIMESTAMP('08-MAR-19 08.23.47.897000000 PM GMT', 'DD-MON-YYYY HH.MI.SS.FF AM') from dual;
The following takes care of that:
SELECT TO_TIMESTAMP(substr(create_time, 1, LENGTH(create_time) -4), 'DD-MON-YYYY HH.MI.SS.FF AM') t from dual;
Try this.
select TO_TIMESTAMP( REPLACE(ts, 'GMT', '')) from test_timestamp;
Remove GMT using REPLACE
WITH A AS (SELECT REPLACE('08-MAR-19 08.23.47.897000000 PM GMT','GMT','') AS D FROM DUAL)
SELECT TO_TIMESTAMP (D, 'DD-MON-YYYY HH.MI.SS.FF AM')
FROM A
Doing something like:
to_timestamp(replace(create_time ,'GMT', null))
relies on your NLS settings, both for the timestamp format - particularly that it has an RR year mask - and the language for the month abbreviation. It would be safer to do:
to_timestamp(replace(create_time, ' GMT', null),
'DD-MON-RR HH.MI.SS.FF AM', 'NLS_DATE_LANGUAGE=ENGLISH')
If the time zone isn't always GMT, but is always a valid and recognised region (not BST, for instance) then you might want to preserve the full date/time including that zone:
to_timestamp_tz(create_time, 'DD-MON-RR HH.MI.SS.FF AM TZR',
'NLS_DATE_LANGUAGE=ENGLISH')
If you want that as a plain timestamp you can cast it, possibly changing to a specific zone first:
cast(to_timestamp_tz(create_time, 'DD-MON-RR HH.MI.SS.FF AM TZR',
'NLS_DATE_LANGUAGE=ENGLISH') as timestamp)
or
cast(to_timestamp_tz(create_time, 'DD-MON-RR HH.MI.SS.FF AM TZR',
'NLS_DATE_LANGUAGE=ENGLISH') at time zone 'Asia/Tokyo' as timestamp)
or normalised to UTC (which won't affect GMT values, of course, as they're essentially the same):
sys_extract_utc(to_timestamp_tz(create_time, 'DD-MON-RR HH.MI.SS.FF AM TZR',
'NLS_DATE_LANGUAGE=ENGLISH'))
db<>fiddle

CST/CDT date to MM/DD/YYYY hh:mm in oracle

I have a csv file with data in timezones including CST and CDT.
For eg:
07-Mar-2017 11:00:00 PM CST
03-Oct-2017 11:00:00 PM CDT
The date field in the csv is being stored as a varchar2(30).
The target date field needs to be converted to the format shown below:
MM/DD/YYYY hh:mm
How can we go about doing this conversion in oracle considering we have two timezines in the source file?
Please help.
Thanks Much
Tina
Use TO_TIMESTAMP_TZ to read it as a TIMESTAMP WITH TIME ZONE data type. If you want to convert it to a common time zone then use AT TIME ZONE 'UTC' to convert it to the UTC time zone (as an example).
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE your_table ( value ) AS
SELECT '07-Mar-2017 11:00:00 PM CST' FROM DUAL UNION ALL
SELECT '03-Oct-2017 11:00:00 PM CDT' FROM DUAL UNION ALL
SELECT '03-Oct-2017 11:00:00 PM CST' FROM DUAL;
Query 1:
SELECT TO_CHAR(
TO_TIMESTAMP_TZ(
value,
'DD-MON-YYYY HH12:MI:SS AM TZD',
'NLS_DATE_LANGUAGE=American'
) AT TIME ZONE 'UTC',
'MM-DD-YYYY HH24:MI'
) AS utc_time
FROM your_table
Results:
| UTC_TIME |
|------------------|
| 03-07-2017 23:00 |
| 10-03-2017 23:00 |
| 10-03-2017 23:00 |

Oracle to_char in query is not working

Im trying to run this below query but its seems to be error
For those data types are varchar
Query
select *
from RP_REPORT_TEMP
where to_char(START_DATE,'FM DD YYYY HH24:MI:SS AM')
>= 'May 01 2016 00:00:00'
and to_char(END_DATE,'FM DD YYYY HH24:MI:SS PM')
<= 'May 31 2016 11:59:00'
and lower(rid) like '%a001%'
order by CAST(cid as INTEGER) asc
Table
|RID |START_DATE |END_DATE |
|--------------------|-------------------------- |-----------------------------|
|A001 |May 1 2016 12:00:00:000AM |May 31 2016 12:00:00:000PM |
|A001 |May 1 2016 12:00:00:000AM |May 31 2016 12:00:00:000PM |
|A001 |May 1 2016 12:00:00:000AM |May 31 2016 12:00:00:000PM |
While i tried to execute this query. Query return some error. How can i fix this ?
Error
SQL Error [1722] [42000]: ORA-01722: invalid number
java.sql.SQLSyntaxErrorException: ORA-01722: invalid number
Why don't you use TO_DATE() on the date instead?
select * from RP_REPORT_TEMP
where START_DATE >= to_date('May 01 2016 12:00:00 AM','MON DD YYYY HH:MI:SS AM')
and END_DATE <= to_date('May 31 2016 11:59:00 AM','MON DD YYYY HH24:MI:SS AM')
and lower(rid) like '%a001%'
Assuming that START_DATE and END_DATE are actually dates, I can spot two main issues in your code:
Casting every row to string is slow and also prevents Oracle from using indexes (unless you have a carefully built function-based index).
Lexicographical sort (aka "A to Z") does not render meaningful results with dates with "May 1". Just think of what sense this list has: Apr, Aug, Dec, Feb, Jan, Jul, Jun, Mar, May, Nov, Oct, Sep
My suggestions are:
Avoid converting dates to string, save for display purposes
Use a more solid format when you have to convert from string to date
As a result:
select *
from RP_REPORT_TEMP
where START_DATE
>= TO_DATE('2016-05-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
and END_DATE
<= TO_DATE('2016-05-31 11:59:00', 'YYYY-MM-DD HH24:MI:SS')
and lower(rid) like '%a001%'
order by CAST(cid as INTEGER) asc
P.S. START_DATE and END_DATE were not dates after all
Try this..
select *
from RP_REPORT_TEMP
where TO_date(START_DATE,'MON DD YYYY HH:MI:SS AM')
>= to_Date('May 01 2016 12:00:00 AM' ,'MON DD YYYY HH:MI:SS AM')
and TO_DATE(END_DATE,'MON DD YYYY HH:MI:SS PM')
<= TO_DATE('May 31 2016 11:59:00 AM' ,'MON DD YYYY HH:MI:SS PM')
and lower(rid) like '%a001%'
order by CAST(cid as INTEGER) asc
select *
from RP_REPORT_TEMP
where TO_date(START_DATE,'MON DD YYYY HH24:MI:SS')
>= to_Date('May 01 2016 12:00:00' ,'MON DD YYYY HH24:MI:SS')
and TO_DATE(END_DATE,'MON DD YYYY HH24:MI:SS')
<= TO_DATE('May 31 2016 11:59:00' ,'MON DD YYYY HH24:MI:SS')
and lower(rid) like '%a001%'
order by CAST(cid as INTEGER) asc
This is what your query should look like:
select *
from rp_report_temp
where to_date(start_date,'FM Mon DD YYYY HH:MI:SS"FMMon DD YYYY HH:MI:SS":000"AM', 'nls_date_language = english')
>= to_date('01/05/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss')
and to_date(end_date,'FM Mon DD YYYY HH:MI:SS":000"AM', 'nls_date_language = english')
<= to_date('31/05/2016 23:59:59', 'dd/mm/yyyy hh24:mi:ss')
and lower(rid) like '%a001%'
order by cast(cid as integer) asc;
Here, I have converted your start and end date columns into a date, based on the fact that a sample string in that column looks like "May 1 2016 12:00:00:000AM" - there's an extra ":000" after the seconds; I'm assuming this is always ":000".
Note how I've made your code nls_date_language parameter independent, by specifically setting that value within the to_date(). This means that if someone else's client has that set to something that's not English, the sql statement will still work for them.
You'll note that I didn't need to do that for the values you're testing, since I changed the format of the string to something that used numbers to represent the months.
You have some fundamental data modelling issues here too - by storing everything as varchar2 you have made a rod for your own back - you've lost all the validation available (what happens if someone puts a string of Feb 30 2015 39:99:99 AM in that column? AWOOGA, AWOOGA, error!). You've made your queries have to work harder (now we've got functions all over the place trying to convert data to the correct datatype).
You should store data in the correct datatype. Dates should be stored as DATE, Timestamps as TIMESTAMP, numbers as NUMBER (with or without specific precision and scale), etc etc.
If your data was stored correctly, then your query would be:
select *
from rp_report_temp
where start_date >= to_date('01/05/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss')
and end_date <= to_date('31/05/2016 23:59:59', 'dd/mm/yyyy hh24:mi:ss')
and lower(rid) like '%a001%'
order by cid asc;

How to convert timestamp to yyyy-mm-dd hh24:mi:ss format in oracle

How to convert 26-Mar-15 03.42.43.601000000 pm to yyyy-mm-dd hh24:mi:ss. Can anyone help me on this ?
First convert your string/varchar2 into a timestamp, and then format it back to a string with your format:
SQL> select to_char
2 ( to_timestamp('26-Mar-15 03.42.43.601000000 pm','dd-Mon-rr hh.mi.ss.ff9 am')
3 , 'yyyy-mm-dd hh24:mi:ss'
4 )
5 from dual
6 /
TO_CHAR(TO_TIMESTAM
-------------------
2015-03-26 15:42:43
1 row selected.
Yo can convert the date string to timestamp by;
select to_timestamp('26-Mar-15 03.42.43.601000000 pm', 'dd-mon-yy hh.mi.ss.FF9 AM')
from DUAL
If you want to get the data in yyyy-mm-dd hh24:mi:ss then use to_char function
select
to_char(
to_timestamp('26-Mar-15 03.42.43.601000000 pm', 'dd-mon-yy hh.mi.ss.FF9 AM'),
'yyyy-mm-dd hh24:mi:ss'
)
from DUAL

How to strip Timestamp up to just seconds?

Given a timestamp value, i.e. "04-SEP-14 03.09.09.272949000 PM", how do I get the date time up to just the seconds part and zeroing out the micro-seconds part?
given: 04-SEP-14 03.09.09.272949000 PM
wish: 04-SEP-14 03.09.09.00 PM
thanks in advance.
You can use the cast function to cast it to a zero-millisecond TIMESTAMP with the construct:
cast(<your column>, timestamp(0))
Using a CTE to pass in your value:
with t as (
select to_timestamp('04-SEP-14 03.09.09.272949000 PM',
'DD-MON-RR HH:MI:SS.FF AM') as tstamp
from dual
)
select to_char(cast(tstamp as timestamp(0)), 'DD-MON-RR HH:MI:SS.FF2 AM')
from t;
TO_CHAR(CAST(TSTAMPASTIMESTAMP(0)),'DD-M
----------------------------------------
04-SEP-14 03:09:09.00 PM
You could also cast it twice, once to DATE to strip the milliseconds, and then back to TIMESTAMP again:
with t as (
select to_timestamp('04-SEP-14 03.09.09.272949000 PM',
'DD-MON-RR HH:MI:SS.FF AM') as tstamp
from dual
)
select to_char(cast(cast(tstamp as date) as timestamp),
'DD-MON-RR HH:MI:SS.FF2 AM')
from t;
TO_CHAR(CAST(CAST(TSTAMPASDATE)ASTIMESTA
----------------------------------------
04-SEP-14 03:09:09.00 PM
... which is doing more work as well as being more typing.
You can't use trunc(date) because that implicitly converts the TIMESTAMP to a DATE, and since a DATE is already at that precision you can't pass SS as the fmt anyway.

Resources