Oracle SQL: convert UTC to CST - sql

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?

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

Show UTC in timestamp Oracle SQL

In Oracle SQL, this:
SELECT to_timestamp('2021-08-11 16:25:54', 'YYYY-MM-DD HH24:MI:SS') FROM DUAL;
Returns:
11-AUG-21 04.25.54.000000000 PM
However, my input timestamp also contains UTC: 2021-08-11 16:25:54 UTC
Desired result:
11-AUG-21 04.25.54.000000000 PM UTC
The docs specify to include Z... However this does not work:
--Invalid date format
SELECT to_timestamp('2021-08-11 16:25:54 UTC', 'YYYY-MM-DD HH24:MI:SS Z') FROM DUAL;
First of all, you need to_timestamp_tz() instead of to_timestamp, and secondly you need to specify correct format: TZR instead of Z:
-- TZR = time zone region
SELECT to_timestamp_tz('2021-08-11 16:25:54 UTC', 'YYYY-MM-DD HH24:MI:SS TZR') FROM DUAL;
You can use at time zone
SELECT to_timestamp('2021-08-11 16:25:54', 'YYYY-MM-DD HH24:MI:SS') at time zone 'UTC' dt
FROM DUAL;
EDIT
Correct version, thanks to #WernfriedDomscheit
SELECT FROM_TZ(to_timestamp('2021-08-11 16:25:54', 'YYYY-MM-DD HH24:MI:SS'), 'UTC') ts
FROM DUAL;

Subtracting hours from Unix Timestamp

The following query selects a unix timestamp. It should be 1pm but says 5pm because of UTC. It needs to be Eastern time 1pm, so I need to subtract 4 hours from it. What's the best way to go about this?
SELECT CAST(to_date('1970-01-01', 'YYYY-MM-DD') + substr(STARTTIME,0,10)/60/60/24 as timestamp)
You shouldn't caluclate manually. You should add or substract the timezone.
Oracle how to convert time in UTC to the local time (offset information is missing)
Here an example-query:
SELECT TO_CHAR (
FROM_TZ (CAST (SYSDATE AS TIMESTAMP), 'UTC')
AT TIME ZONE 'EUROPE/BERLIN',
'YYYY-MM-DD HH24:MI:SS TZH:TZM TZR')
AS BERLIN_Time_complete,
TO_CHAR (
FROM_TZ (CAST (SYSDATE AS TIMESTAMP), 'UTC')
AT TIME ZONE 'UTC',
'YYYY-MM-DD HH24:MI:SS TZH:TZM TZR')
AS UTC_Complete,
TO_CHAR (
FROM_TZ (CAST (SYSDATE AS TIMESTAMP), 'UTC')
AT TIME ZONE 'EUROPE/BERLIN',
'YYYY-MM-DD HH24:MI:SS TZH:TZM')
AS BERLIN_Time_complete,
TO_CHAR (
FROM_TZ (CAST (SYSDATE AS TIMESTAMP), 'UTC')
AT TIME ZONE 'EUROPE/BERLIN',
'TZH:TZM')
AS BERLIN_Timezone,
TO_CHAR (
FROM_TZ (CAST (SYSDATE AS TIMESTAMP), 'UTC')
AT TIME ZONE 'EUROPE/BERLIN',
'TZR')
AS Timezone_Name
FROM DUAL;
The key is for Format:
YYYY: Year with four digits (0000-9999 ex: 2018)
MM: Month with two digits (01-12)
DD: Day with two digits (01-31)
HH24: Hour 00-23
MI: Minutes 00-59
SS: Seconds 00-59
TZH: Timezone-Hours
TZM: Timezone-Minutes (There are timezones with 30mins offset)
TZR: Name of the timezone
You should play around with those, to understand the to_date()/to_char(). You'll need it.
If you realy want to add hours. Here an example:
select sysdate + INTERVAL '2' HOUR from dual;
You can try this :
SELECT TO_CHAR(sysdate, 'DD-MON-YYYY HH24:MI:SS') AS myDate
FROM dual;
For more information read this document.

ORACLE SQL: add time to a timestamp with timezone

I need to add seconds and substract variables with type TIMESTAMP WITH TIMEZONE, however, to my understanding, adding numbers to such data causes the information about the timezone to be lost, perhaps because it's converted to a DATE type
That is:
SELECT FROM_TZ(
TO_TIMESTAMP(
TO_DATE('03/09/2012 2:30:30','DD/MM/YYYY HH:MI:SS')
)
, 'America/Chicago')
FROM DUAL;
Gives:
03/09/2012 00:00:00, -05:00
Then
SELECT FROM_TZ(
TO_TIMESTAMP(
TO_DATE('03/09/2012 2:30:30','DD/MM/YYYY HH:MI:SS')
)
, 'America/Chicago') + 1/24 -- add 1 hour
FROM DUAL;
Gives
03/09/2012 01:00:00
and loses the timezone information.
But
SELECT FROM_TZ(
TO_TIMESTAMP(
TO_DATE('03/09/2012 2:30:30','DD/MM/YYYY HH:MI:SS'))
, 'America/Chicago') + INTERVAL '1' hour
FROM DUAL;
Correctly gives
03/09/2012 01:00:00,000000000 -05:00
However the INTERVAL.. syntax expect a char constant, so I can't use that with variables.
How can I perform that kind of arithmetic with TIMESTAMP WITH TIME ZONE datatype while retaining timezone information?
TIA
You can use the NUMTODSINTERVAL function to convert a number to an interval.
SELECT FROM_TZ( TIMESTAMP '2012-10-08 00:00:00','-5:00')
+ NUMTODSINTERVAL(1,'HOUR')
FROM dual;

Need help: Timezone related Oracle SQL QUERY

I need your help in understanding the below query.
SELECT To_date(To_char(( ( To_timestamp_tz(From_tz(Cast(l_end_date AS TIMESTAMP)
,
dbtimezone))
) AT
TIME
ZONE ( l_time_zone ) ),
'YYYY-MM-DD HH24:MI:SS'
), 'YYYY-MM-DD HH24:MI:SS')
FROM dual
where l_end_date = 31-Dec-2018
Well, ultimately it converts the date 31-Dec-2018 at midnight into whatever local timezone date you indicate with l_time_zone. E.g., for me with dbtimezone = +00:00 and l_time_zone set to Australia/Sydney I get 31/12/2018 11:00:00 AM.
But to fully understand you may just want to look at each function's documentation:
DBTIMEZONE
TO_TIMESTAMP_TZ
FROMTZ
TO_DATE
TO_CHAR
AT TIME ZONE