GMT+5.30 string convert to Date in Oracle - oracle

As per below LINK,
I try to convert my string 'Tue May 24 20:11:20 GMT+05:30 2011' to date in oracle
select TO_TIMESTAMP_TZ('Tue May 24 20:11:20 GMT+05:30 2011', 'DY MON DD HH24:MI:SS TZDTZH:TZM YYYY') from dual;
But it's throw the error
ORA-01857: not a valid time zone
01857. 00000 - "not a valid time zone"
Please guide me how to convert with GMT Zone Name in Date conversion.

I don't think GMT has any significance here. Since, +5:30 always means it is relative to GMT, you can remove GMT from your string and then convert.
SELECT TO_TIMESTAMP_TZ (
REPLACE ('Tue May 24 20:11:20 GMT+05:30 2011', 'GMT'),
'DY MON DD HH24:MI:SS TZH:TZM YYYY')
FROM DUAL;
Or,
You can do this also, by putting GMT in double quotes.
SELECT TO_TIMESTAMP_TZ (
'Tue May 24 20:11:20 GMT+05:30 2011',
'DY MON DD HH24:MI:SS "GMT"TZH:TZM YYYY')
FROM DUAL;

Related

How to convert varchar with short time zone to timestamp in oracle

We have date stored in varchar2 column as 'Tue Dec 18 16:49:31 EST 2018', I would like to convert this to timestamp. Tried with to_timestamp('Tue Dec 18 16:49:31 EST 2018','DY Mon DD HH24:MI:SS TS YYYY') but not working. Please help.
If you like to preserve the time zone information, you have to use TO_TIMESTAMP_TZ, otherwise you can do it like this:
SELECT
TO_TIMESTAMP_TZ(
REGEXP_REPLACE(
'Tue Dec 18 16:49:31 EST 2018',
'\w+ (\w+) (\d+) (\d\d:\d\d:\d\d) (\w+) (\d+)',
'\5-\1-\2 \3 \4'
),
'YYYY-Mon-DD HH24:MI:SS TZR',
'NLS_DATE_LANGUAGE=American'),
TO_TIMESTAMP(
REGEXP_REPLACE(
'Tue Dec 18 16:49:31 EST 2018',
'\w+ (\w+) (\d+) (\d\d:\d\d:\d\d) \w+ (\d+)',
'\4-\1-\2 \3'
),
'YYYY-Mon-DD HH24:MI:SS',
'NLS_DATE_LANGUAGE=American')
FROM DUAL;
However, it will fail for EDT, see:
SELECT TZNAME, TZABBREV, TZ_OFFSET(TZNAME)
FROM V$TIMEZONE_NAMES
WHERE TZNAME IN ('EST','EDT')
You could use REPLACE('Tue Dec 18 16:49:31 EDT 2018', 'EDT', 'EST5EDT') to make it working.

Oracle TO_DATE format, symbol for "any character"

In this answer the following query is suggested:
SELECT TO_DATE(
'Thu Nov 24 15:20:52 CET 2016',
'DY MON DD HH24:MI:SS "CET" YYYY'
)
FROM DUAL
¿ there are some character to be used in the format with the meaning of "any" ? I like replace "CET" in the format string by something like "..." or "###", that is:
'DY MON DD HH24:MI:SS ... YYYY'
One example, ¿ which format will accept all the following date strings :
2017-12-31
2017_12_31
2017x12x31
You can extract relevant part by regular expression.
select
TO_DATE(
regexp_substr('Thu Nov 24 15:20:52 CET 2016', '^.+\d{2}:\d{2}:\d{2}')
||regexp_substr('Thu Nov 24 15:20:52 CET 2016', ' \d{4}$'),
'DY MON DD HH24:MI:SS YYYY')
from dual;
or
select
TO_DATE(
REGEXP_REPLACE('Thu Nov 24 15:20:52 CET 2016', '\w+ (\d{4})$', '\1'),
'DY MON DD HH24:MI:SS YYYY')
from dual;
Here's another way using to_timestamp_tz:
WITH sample_data AS (SELECT 'Thu Nov 24 15:20:52 CET 2016' str FROM dual UNION ALL
SELECT 'Fri Dec 11 23:16:39 PST 2015' str FROM dual)
SELECT str,
to_timestamp_tz(str, 'Dy Mon dd hh24:mi:ss TZR yyyy', 'nls_date_language = english') timestamp_at_orig_tz,
CAST(to_timestamp_tz(str, 'Dy Mon dd hh24:mi:ss TZR yyyy', 'nls_date_language = english') AS DATE) dt,
CAST(to_timestamp_tz(str, 'Dy Mon dd hh24:mi:ss TZR yyyy', 'nls_date_language = english') AT TIME ZONE '-5:00' AS DATE) dt_at_utc_minus_5,
cast(sys_extract_utc(to_timestamp_tz(str, 'Dy Mon dd hh24:mi:ss TZR yyyy', 'nls_date_language = english')) AS DATE) dt_at_utc
FROM sample_data;
STR TIMESTAMP_AT_ORIG_TZ DT DT_AT_UTC_MINUS_5 DT_AT_UTC
---------------------------- -------------------------------- ------------------- ------------------- -------------------
Thu Nov 24 15:20:52 CET 2016 24-NOV-16 15.20.52.000000000 CET 24/11/2016 15:20:52 24/11/2016 09:20:52 24/11/2016 14:20:52
Fri Dec 11 23:16:39 PST 2015 11-DEC-15 23.16.39.000000000 PST 11/12/2015 23:16:39 12/12/2015 02:16:39 12/12/2015 07:16:39
I've given a three different ways of converting the timestamp-as-a-string into a date:
Convert the timestamp as is into a date. Note that this will lose any timestamp information you have - useful if you really don't care about timezone information.
Convert the timestamp into a specific timezone (in my example, UTC - 5) before converting it into a date.
Convert the timestamp into UTC before converting it into a date (you can use the previous method to do this, but sys_extract_utc() is a little more self-explanatory, IMHO, which can only aid readability and maintainability!).
With your updated question (which seems to be more around the date part separator, not the timezone), the following should do the trick:
WITH sample_data AS (SELECT '2017-12-31' dt_str FROM dual UNION ALL
SELECT '2017_12_31' dt_str FROM dual UNION ALL
SELECT '2017x12x31' dt_str FROM dual)
SELECT dt_str,
to_date(regexp_replace(dt_str,
'([[:digit:]]{4}).([[:digit:]]{2}).([[:digit:]]{2})',
'\1-\2-\3'), 'yyyy-mm-dd')
FROM sample_data;
DT_STR DT
---------- ----------
2017-12-31 31/12/2017
2017_12_31 31/12/2017
2017x12x31 31/12/2017

How to convert String with timezone to Date

How to convert below string to Date in Oracle
Wed Jan 13 23:01:24 GMT 2016
Tried below and this get's date as
SELECT TO_CHAR(SYSDATE, 'DY MON DD HH24:MM:SS YYYY') FROM dual;
FRI AUG 26 14:08:04 2016
Eventually, Wanted something like this
SELECT TO_CHAR('Wed Jan 13 23:01:24 GMT 2016', 'DY MON DD HH24:MM:SS ??? YYYY') FROM dual;
If the time zone is always a recognised abbreviation you can do:
select to_timestamp_tz('Wed Jan 13 23:01:24 GMT 2016', 'Dy Mon DD HH24:MI:SS TZD YYYY')
from dual;
TO_TIMESTAMP_TZ('WEDJAN1323:01:24GMT2016','DYMONDDHH24:MI:SSTZDYYYY')
---------------------------------------------------------------------
2016-01-13 23:01:24 EUROPE/LONDON
You can't convert directly to a date because the time zone format elements aren't allowed in to_date(). If you had a fixed value - always GMT - you could ignore that by treating it as a literal, but you don't.
If you want it as a timestamp or a date, rather than a timestamp with time zone, you need to decide how to convert it. You can assume it's local time and essentially ignore the time zone by casting it, or you can adjust it to a specific time zone, e.g. UTC. There are various ways, here are a couple with a CTE to provide your sample and one in another zone (well, in summertime anyway so you get a different string):
with t (str) as (
select 'Wed Jan 13 23:01:24 GMT 2016' from dual
union all select 'Fri Aug 26 19:53:27 BST 2016' from dual
)
select to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY') as tstz,
cast(to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY') as timestamp) as ts,
cast(to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY') as date) as dt,
sys_extract_utc(to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY')) as tsutc
from t;
TSTZ TS DT TSUTC
--------------------------------- ------------------- ------------------- -------------------
2016-01-13 23:01:24 EUROPE/LONDON 2016-01-13 23:01:24 2016-01-13 23:01:24 2016-01-13 23:01:24
2016-08-26 19:53:27 EUROPE/LONDON 2016-08-26 19:53:27 2016-08-26 19:53:27 2016-08-26 18:53:27
Exactly how you handle it depends on what you really need, of course.
Unfortunately that doesn't always work with abbreviations; Oracle doesn't necessarily recognise the values you see in Unix date command output, and the ones it does recognise aren't always available. Changing the session time zone can break it:
alter session set time_zone = 'America/Los_Angeles';
select to_timestamp_tz('Wed Jan 13 23:01:24 GMT 2016', 'Dy Mon DD HH24:MI:SS TZD YYYY')
from dual;
ORA-01857: not a valid time zone
You can change the session time zone to one that does recognise it (Europe/London) but that's a hack and won't work for all values anyway. It doesn't help that abbreviations can mean more than one thing.
If you have a list of known expected values and know what they really represent to you, you can swap the abbreviation for a region, but it doesn't really scale:
select to_timestamp_tz(
replace(replace('Wed Jan 13 23:01:24 GMT 2016', 'GMT', 'Europe/London'),
'BST', 'Europe/London'),
'Dy Mon DD HH24:MI:SS TZR YYYY') from dual;
Or with multiple output formats:
with t1 (str) as (
select 'Wed Jan 13 23:01:24 GMT 2016' from dual
union all select 'Fri Aug 26 19:53:27 BST 2016' from dual
),
t2 (adj_str) as (
select replace(replace(str, 'GMT', 'Europe/London'), 'BST', 'Europe/London')
from t1
)
select to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY') as tstz,
cast(to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY') as timestamp) as ts,
cast(to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY') as date) as dt,
sys_extract_utc(to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY')) as tsutc
from t2;
You'd need to have nested replace calls (or regexp_replace to reduce the repetition a little) for each abbreviation you expect; or could have a function that hides that mess away from your main query.
You need to use the TO_TIMESTAMP_TZ function.
The following example converts a character string to a value of TIMESTAMP WITH TIME ZONE:
SELECT TO_TIMESTAMP_TZ('1999-12-01 11:00:00 -8:00',
'YYYY-MM-DD HH:MI:SS TZH:TZM') FROM DUAL;
The -8:00 is the timezone.
https://docs.oracle.com/cd/B12037_01/server.101/b10759/functions179.htm#SQLRF06143

inserting data into Timestamp datatype column is returning ORA-01858: a non-numeric character was found where a numeric was expected

Our application is trying to insert data into Oracle database in the format "Tue Feb 26 15:30:00 EST 2016" into column(FLD_TIMESTAMP) of Timestamp(6) datatype .We are receiving "ORA-01843: not a valid month" .
Wrote a trigger to convert the input data into timestamp format as below :
SQL> create or replace trigger test_wifi before insert on ISG_SESSION_tempfeb15 for each row
2 begin
3 :NEW.fld_timestamp :=to_char(to_timestamp_tz(':NEW.fld_timestamp','Dy Mon DD hh24:mi:ss TZD YYYY'),'DD-MON-YY hh:mi:ss AM');
4 end;
5 /
Trigger created.
While i am trying to insert data , it is still erroring out :
SQL> insert into ISG_SESSION_tempfeb15(isg_session_id,mac_address,nas_ip,fld_timestamp,created_dte)
2 values('5','6','7','Wed Jan 13 16:29:00 EST 2016','16-FEB-16 03:05:00.0000');
values('5','6','7','Wed Jan 13 16:29:00 EST 2016','16-FEB-16 03:05:00.0000')
*
ERROR at line 2:
ORA-01858: a non-numeric character was found where a numeric was expected
Can someone please tell me how to resolve this ? Thanks in Advance .
Why do you have to_char after converting to timestamp?
That's because you can't do the data conversion as part of a trigger like that. The issue is that the insert statement expects the data to be passed in with the correct format.
What you need to do is scrap your trigger and amend your insert statement to something like:
insert into ISG_SESSION_tempfeb15 (isg_session_id,
mac_address,
nas_ip,
fld_timestamp,
created_dte)
values ('5',
'6',
'7',
to_timestamp_tz('Wed Jan 13 16:29:00 EST 2016', 'Dy Mon dd hh24:mi:ss TZR yyyy'),
to_timestamp('16-FEB-2016 03:05:00.0000', 'dd-MON/yyyy hh24:mi:ss.ff4'));
N.B. I have amended the year of the created_dte that you're passing in to have four digits, not two. Y2K isn't a fairy tale!
Also, please note that if your column has a datatype of TIMESTAMP(6) and not TIMESTAMP(6) WITH TIME ZONE, you will lose any information about the timezone of the data.
eg.
create table t1 (col1 timestamp(6),
col2 timestamp(6) with time zone);
insert into t1 values (to_timestamp_tz('Wed Jan 13 16:29:00 EST 2016', 'Dy Mon dd hh24:mi:ss TZR yyyy'),
to_timestamp_tz('Wed Jan 13 16:29:00 EST 2016', 'Dy Mon dd hh24:mi:ss TZR yyyy'));
insert into t1 values (to_timestamp_tz('Wed Jan 13 16:29:00 UTC 2016', 'Dy Mon dd hh24:mi:ss TZR yyyy'),
to_timestamp_tz('Wed Jan 13 16:29:00 UTC 2016', 'Dy Mon dd hh24:mi:ss TZR yyyy'));
commit;
select * from t1;
COL1 COL2
--------------------------- ----------------------------------
13/01/2016 16:29:00.000000 13/01/2016 16:29:00.000000 -05:00
13/01/2016 16:29:00.000000 13/01/2016 16:29:00.000000 +00:00
See how the first column looks like it contains the same value, but the second column reveals that it doesn't?
Try change ':NEW.fld_timestamp' to :NEW.fld_timestamp
:NEW.fld_timestamp :=to_char(to_timestamp_tz(:NEW.fld_timestamp,'Dy Mon DD hh24:mi:ss TZD YYYY'),'DD-MON-YY hh:mi:ss AM');
this is your problem

specifying a date/time format with timezone

Is it possible to display sysdate in the following format?
Wed Oct 16 15:04:44 MDT 2013
This comes out of unix date format.
echo `date`
EDIT: the latest version is missing timezone information. Also, I am not sure if this is the most elegant solution :
SELECT TO_CHAR (sysdate, 'DY') || ' ' || to_char(sysdate, 'MON DD') || ' ' || to_char(sysdate, 'HH24:MM:SS' ) || ' ' || to_char(sysdate, 'YYYY' )
FROM DUAL ;
sysdate returns value of date data type, which does not contain information about timezone. To be able to display abbreviated version of timezone region you need to operate on values of timestamp with time zone data types and use TZD format element in a date time format mask:
select to_char( cast(sysdate as timestamp with local time zone)
, 'Dy Mon dd hh24:mi:ss TZD yyyy') as res
from dual
Result:
RES
-------------------------------
Thu Oct 17 02:14:00 PDT 2013
Edit
Wed Oct 16:12:0 2013 is what i got
Try to explicitly specify exact time zone region for a session. Because there are might be several time zone regions associated with one offset and oracle wont be able to choose one and returns null. So before executing the query execute alter session set time_zone='<<specify_exact_time_zone_region>>'. For example:
SQL> alter session set time_zone='Canada/Mountain';
Session altered.
SQL> select to_char( cast(sysdate as timestamp with local time zone)
2 , 'Dy Mon dd hh24:mi:ss TZD yyyy') as res
3 from dual;
RES
-------------------------------
Thu Oct 17 02:51:14 MDT 2013

Resources