VARCHAR2 to TIMESTAMP conversion in ORACLE 12c - oracle

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

Related

Converting a date in 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

Trying to covert timestamp to date causes error

select to_date('25-MAY-20 12.10.12.320000 PM', 'dd-mon-yy hh:mi:ss pm') from dual;
getting the error
"am or pm required"
Oracle only stores precision up to seconds in a date type. If you want fractional seconds (e.g. milliseconds) you will need to use a timestamp column. But in any case, your current format mask is wrong. Try this instead:
SELECT TO_TIMESTAMP('25-Feb-20 12.10.12.320000 PM', 'dd-mon-yy hh.mi.ss.ff6 pm')
FROM dual
Demo
You can convert your timestamp into char and then convert to date.
Example with systimestamp:
select to_date(
to_char(systimestamp,'dd-mon-yy hh:mi:ss PM')
, 'dd-mon-yy hh:mi:ss PM')
from dual;

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.

Oracle Time Zones Conversion (using from_tz)

I'm trying to convert a time (date + time) from one time zone to another. In the query below, I'm trying to convert a time from EST ("America/New_York") to PST ("America/Los_Angeles"). The query is partially working; the results:
DATABASE_DATE = 2012-02-13 1:00:00 PM
LOCALTIME (what I get): 2012-02-12 10:00:00 AM.
So the time is good but the date is wrong. It should be 2012-02-13 instead of 2012-02-12.
Am I doing something wrong? Here's my query:
select to_date( to_char( ( from_tz( to_timestamp( DATABASE_DATE
, 'YYYY-MM-DD HH:MI:SS')
,'America/New_York')
at time zone 'America/Los_Angeles')
,'YYYY-MM-DD HH:MI:SS')
,'YYYY-MM-DD HH:MI:SS') as localtime
from table
Thanks
to_timestamp() gets a string (VARCHAR2, CHAR ...) if you try to give it a date, then oracle will convert it to a string according to NLS_DATE_FORMAT which might vary in different environments and return unexpected results (as in this case).
What you should do is use to_char first, so your query can look like this:
select to_date(to_char((from_tz(to_timestamp(to_char(DATABASE_DATE, 'YYYY-MM-DD HH:MI:SS PM'), 'YYYY-MM-DD HH:MI:SS PM') ,'America/New_York')
at time zone 'America/Los_Angeles'),'YYYY-MM-DD HH:MI:SS PM'),'YYYY-MM-DD HH:MI:SS PM') as localtime
from table
UPDATE: if I understand you right then you want something like this:
select to_char((from_tz(to_timestamp(to_char(DATABASE_DATE, 'YYYY-MM-DD HH:MI:SS PM'), 'YYYY-MM-DD HH:MI:SS PM') ,'America/New_York')
at time zone 'America/Los_Angeles'),'YYYY-MM-DD HH:MI:SS PM TZD') as localtime
from table
SELECT TO_CHAR(NEW_TIME(systimestamp,'EST','PST'), 'DD-MON-YY HH24:MI:SS') AS converted_timestamp_column FROM DUAL;
Please try this as well .There is a function for this purpose in oracle
https://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_functions_2036.htm
select NEW_TIME (TO_DATE ('2011/11/11 01:45', 'yyyy/mm/dd HH24:MI'), 'AST', 'MST') from dual;

Resources