Inserting timestamp with timezone in text in SQL - sql

I created an insert statement that inserts the current time into a field with datatype:
TIMESTAMP(6) WITH TIME ZONE
insert into(
...
)
values(
9645
,0
,CAST(CURRENT_TIMESTAMP AS TIMESTAMP WITH TIME ZONE)
,user
,CAST(CURRENT_TIMESTAMP AS TIMESTAMP WITH TIME ZONE)
,0
,'APPROVED_P'
,1
,1
)
This works fine, but for one problem
I would like to have the timezone in text as well, but I'm unable to find a solution. Hope someone can help me out.

Time zone +01:00 is not the same as CET. Mayor difference is CET considers daylight saving times whereas +01:00 does not.
If you want time zone CET then you must set your session time zone accordingly with ALTER SESSION SET TIME_ZONE = 'CET'; or you set CURRENT_TIMESTAMP AT TIME ZONE 'CET' instead of CURRENT_TIMESTAMP
You should see the difference when you run this:
SELECT SESSIONTIMEZONE,
TO_CHAR(CURRENT_TIMESTAMP, 'yyyy-mm-dd hh24:mi:ss tzh:tzm tzr tzd'),
TO_CHAR((current_TIMESTAMP - INTERVAL '6' MONTH), 'yyyy-mm-dd hh24:mi:ss tzh:tzm tzr tzd')
FROM DUAL;

Related

Convert epoch time to timestamp in oracle database with system timezone

Can someone please suggest me how to convert epoch time to timestamp in oracle including the database timezone. I am currently using below code:
cast ( TO_TIMESTAMP_TZ('1970-01-01 00:00:00.0 UTC', 'YYYY-MM-DD HH24:MI:SS.FF TZR') + NUMTODSINTERVAL(value/1000, 'SECOND') as timestamp with local time zone)
But it appears this is converting to the sessiontimezone. I need it to be converted to dbtimezone
(In my case select dbtimezone gives PST time and select sessiontimezone gives Asia/Calcutta time.)
Data type timestamp with local time zone always shows date/time at SESSIONTIMEZONE
Try
(TO_TIMESTAMP_TZ('1970-01-01 00:00:00.0 UTC', 'YYYY-MM-DD HH24:MI:SS.FF TZR') + NUMTODSINTERVAL(value/1000, 'SECOND')) AT TIME ZONE DBTIMEZONE
Or with literals:
(Timestamp '1970-01-01 00:00:00 UTC' + value/1000 * INTERVAL '1' SECOND) AT TIME ZONE DBTIMEZONE

date/time Conversion between different timezones

I am using the following sql to covert a date/time value from one timezone to another
from_tz(cast(to_date(to_char(q.created_date, 'DDMMYYYY:HH24:MI:SS'),
'DDMMYYYY:HH24:MI:SS') as timestamp), 'Europe/London') at time zone 'America/New_York'
else null end as Message_Rcd_Date_Time
output from the above is as follows:
29-OCT-2016 14:28:16.000000 -04:00
What I want to do is output this date/time as shown below, excluding the timezone, can you please tell me what I need to change in order to achieve this?
29-OCT-2016 14:28:16
First let's dissolve your expression
FROM_TZ(CAST(TO_DATE(TO_CHAR(q.created_date, 'DDMMYYYY:HH24:MI:SS'), 'DDMMYYYY:HH24:MI:SS') AS TIMESTAMP), 'Europe/London') AT TIME ZONE 'America/New_York'
does following:
TO_CHAR(q.created_date, 'DDMMYYYY:HH24:MI:SS') -> Convert created_date value to VARCHAR2
TO_DATE(..., 'DDMMYYYY:HH24:MI:SS') -> Convert it back to a DATE
CAST(... AS TIMESTAMP) -> Convert it to a TIMESTAMP (without time zone)
FROM_TZ(..., 'Europe/London') -> Attach time zone 'Europe/London' to it
... AT TIME ZONE 'America/New_York' -> Convert to time zone 'America/New_York'
Point 1,2 and 3 are useless! Since created_date is a TIMESTAMP you can do it shorter
TO_CHAR(FROM_TZ(q.created_date, 'Europe/London') AT TIME ZONE 'America/New_York', 'DD-MON-YYYY HH24:MI:SS')
In case your SESSIONTIMEZONE is Europe/London you can even make
TO_CHAR(q.created_date AT TIME ZONE 'America/New_York', 'DD-MON-YYYY HH24:MI:SS')
Not sure about Oracle but below query can help.
SELECT SUBSTR((cast(to_date(to_char(q.created_date, 'DDMMYYYY:HH24:MI:SS'),
'DDMMYYYY:HH24:MI:SS') as timestamp), 'Europe/London') , 1, 20) at time zone 'America/New_York'
else null end as Message_Rcd_Date_Time;
If it would have been SQL Server only LEFT function would have worked.

Different results for TO_TIMESTAMP_TZ and CAST AS TIMESTAMP WITH LOCAL TIME ZONE in Oracle DB

I have an Oracle 11g database and I'm trying to experiment with how DST is handled with TIMESTAMP datatypes (especially ones created from incoming data that doesn't have a time zone included). I'm seeing a difference in behavior when using TO_TIMESTAMP_TZ() vs CAST(DATE as TIMESTAMP WITH LOCAL TIME ZONE) that I can't explain. I would expect that the resulting datatype is a zoned timestamp regardless of how it is created and any operation on it would be identical but it does not appear that this is the case.
Any idea why when using the CAST option the "extra" hour created by the Fall DST change isn't being taken into account in the INTERVAL math? I would expect both rows of the query below to be identical.
Query:
select to_timestamp_tz('11/1/2015 1:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR') + interval '2' hour as DST_PLUS_2, -- this is a post DST jump time
to_timestamp_tz('11/1/2015 12:59 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR') + interval '2' hour as PRE_DST_PLUS_2, -- this is a pre DST jump time
to_char(to_timestamp_tz('11/1/2015 1:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR'), 'TZR') as TZR
from dual
union all
select cast(to_date('11/1/2015 1:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone) + interval '2' hour as DST_PLUS_2,
cast(to_date('11/1/2015 12:59 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone) + interval '2' hour as PRE_DST_PLUS_2,
to_char(cast(to_date('11/1/2015 1:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone), 'TZR') as TZR
from dual;
Results:
DST_PLUS_2 PRE_DST_PLUS_2 TZR
01-NOV-15 03.00.00.000000000 AM US/PACIFIC 01-NOV-15 01.59.00.000000000 AM US/PACIFIC US/PACIFIC
01-NOV-15 03.00.00.000000000 AM US/PACIFIC 01-NOV-15 02.59.00.000000000 AM US/PACIFIC US/PACIFIC
It looks like this comes down to the fact that TO_TIMESTAMP_TZ attempts to infer the TZD element of the TIMESTAMP from the date while CAST AS TIMESTAMP WITH LOCAL TIME ZONE will take the current TZD of the database regardless of when the date is. Or they just have different default behaviors for picking which of the 1AM times (pre or post time change) to choose. This difference in behavior is causing the resulting hour to be different by one.
Thanks ruudvan!
Query:
select to_char(to_timestamp_tz('11/1/2015 1:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR'), 'TZD') as TZD_TO_TS_TZ_1,
to_char(cast(to_date('11/1/2015 1:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone), 'TZD') as TZD_CAST_1,
to_char(to_timestamp_tz('11/1/2015 12:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR'), 'TZD') as TZD_TO_TS_TZ_12,
to_char(cast(to_date('11/1/2015 12:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone), 'TZD') as TZD_CAST_12
from dual;
Results:
TZD_TO_TS_TZ_1 TZD_CAST_1 TZD_TO_TS_TZ_12 TZD_CAST_12
PST PDT PDT PDT
Data type TIMESTAMP WITH TIME ZONE stores the time zone information. When you insert 11/1/2015 1:00 AM US/Pacific then that is what is stored and that is what you get when you select it.
Data type TIMESTAMP WITH TIME LOCAL ZONE also stores time zone information. However, the value is always shown in current user session time zone SESSIONTIMEZONE. In principle Oracle put the value always in ({TIMESTAMP WITH TIME ZONE} value) AT TIME ZONE SESSIONTIMEZONE
DATE does not store any time zone information. If you run CAST({DATE value} as timestamp with local time zone) then Oracle runs basically FROM_TZ({DATE value}, SESSIONTIMEZONE) as timestamp with local time zone). I.e. it attaches the current user session time zone (which could be different to US/Pacific) to DATE value and then it converts the time zone, if required.
So the result of your query really depends on your current session timezone SESSIONTIMEZONE. Note, this might be US/Pacific or +07:00 / +08:00. If it is set to US/Pacific then daylight saving times are taken into account. For UTC offsets like +07:00 or +08:00 the time zones are fixes, i.e. daylight saving times are not considered.

I want to adjust a date for summer/winter time and time zone when insterting it into a table

I have a date and time variable in TABLE_A that is in GMT. I want to insert this date and time into TABLE_B, but I want the insterted value to be adjusted for time zone and summer/winter time.
That is:
INSERT into TABLE_A (ADJUSTED_DATE_AND_TIME)
SELECT GMT_DATE_AND_TIME [Perform proper adjustments here..?]
FROM TABLE_A
Can I do this? In that case, how do I write ?
Thank.
I think you can simply convert the GMT/UTC time. However, you have to take the full region name of your time zone.
SELECT TIMESTAMP '2014-06-10 12:00:00 +00:00' AT TIME ZONE 'Europe/Zurich' AS summer FROM dual;
SUMMER
---------------------------------------
10.06.2014 14:00:00.000000000 +02:00
SELECT TIMESTAMP '2014-12-10 12:00:00 +00:00' AT TIME ZONE 'Europe/Zurich' AS winter FROM dual;
WINTER
---------------------------------------
10.12.2014 13:00:00.000000000 +01:00
Since your source value is data type DATE you have to do following steps.
Cast DATE to TIMESTAMP
Set Time zone of the value using FROM_TZ
Convert the value to new time zone using AT TIME ZONE '...'
Cast the value to DATE
Written in a single statement it is
select
CAST(FROM_TZ(CAST(sy_sttime AS TIMESTAMP), 'UTC') AT TIME ZONE 'Europe/Zurich' AS DATE)
from sy_request
or a bit less clear
select
CAST((CAST(sy_sttime AS TIMESTAMP) AT TIME ZONE 'UTC') AT TIME ZONE 'Europe/Zurich' AS DATE)
from sy_request

Oracle SQL: convert UTC to CST

I would like to convert UTC date/time to local CST.
The below function works however it gives 6 hours difference when there should only be 5 hours (until day light saving on 11/2/2014).
CAST((FROM_TZ(CAST(utc_date AS TIMESTAMP),'UTC') AT TIME ZONE 'CST') AS DATE) cst_date
also tried a variation
to_date(to_char((from_tz(to_timestamp(to_char(utc_date, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') ,'UTC')
at time zone 'CST'),'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS') as cst_date,
Using the "US/Central" as the target timezone seems to produce the right result.
select from_tz(CAST ('15-oct-2014' AS TIMESTAMP),'GMT') at TIME ZONE 'US/Central' with_daylight_savings,
from_tz(CAST ('15-nov-2014' AS TIMESTAMP),'GMT') at TIME ZONE 'US/Central' without_daylight_savings
from dual;
WITH_DAYLIGHT_SAVINGS WITHOUT_DAYLIGHT_SAVINGS
--------------------------------------------------------------------------------------
14-OCT-14 07.00.00.000000000 PM US/CENTRAL 14-NOV-14 06.00.00.000000000 PM US/CENTRAL
Use timezone region instead of timezone abbr ('CST'). You may find the desired timezone here:
SELECT * from v$timezone_names where tzabbrev = 'CST';
Maybe you need 'CST6CDT' instead of 'CST'
Maybe a stupid approach, but what do you get from this query?
SELECT
TO_CHAR((TIMESTAMP '2014-01-01 00:00:00' + LEVEL * INTERVAL '1' DAY) AT TIME ZONE 'America/Chicago', 'yyyy-mm-dd hh24:mi TZH:TZM') AS dst,
TO_CHAR((FROM_TZ(CAST(DATE '2014-01-01' AS TIMESTAMP), 'UTC') + LEVEL * INTERVAL '1' DAY) AT TIME ZONE 'America/Chicago', 'yyyy-mm-dd hh24:mi TZH:TZM') AS dst
FROM dual
CONNECT BY LEVEL <= 365;
Is it as expected?