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
Related
This question already has answers here:
Timezone date format in Oracle
(2 answers)
Closed 1 year ago.
I am looking for a query in Oracle 12c to convert a 18-12-2003 13:15:00 to 2003-12-18T13:15:00+01:00 in European time zone as datetime datatype.
Is that possible or am I missing something?
First you need to convert the string (I assume your input data is a string, rather than proper DATE or TIMESTAMP value), then you can attach the time zone.
There are several time zones in Europe, you must be more specific.
FROM_TZ(TO_TIMESTAMP('18-12-2003 13:15:00', 'DD-MM-YYYY HH24:MI:SS'), 'Europe/...')
Once you did that, you can output the result in arbitrary format:
TO_CHAR(
FROM_TZ(TO_TIMESTAMP('18-12-2003 13:15:00', 'DD-MM-YYYY HH24:MI:SS'), 'Europe/...'),
'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM'
)
If you want to convert all dates in the column to that format for the time zone CET and you are sure that the offset always is 1, then you could do this:
SELECT TO_CHAR(FROM_TZ(TIMESTAMP '2000-03-28 08:00:00', '1:00'),'YYYY"-"MM"-"DD"T"HH24":"MI":"SSTZR')
FROM DUAL;
However, the question is what to do with daylight savings time. Is the offset going to change when DST goes into effect ? There are a lot of considerations there - this question (credits to #Wernfried Domscheit) has a nice overview.
For example if you data is in UTC time zone and you want to display it in CET, then you could convert it like this:
Note there is 2 hours offset in summer and 1 in winter.
WITH dates (season,dt) AS
(
SELECT 'summer', TO_DATE('01-AUG-2021','DD-MON-YYYY') FROM DUAL UNION ALL
SELECT 'winter', TO_DATE('01-JAN-2021','DD-MON-YYYY') FROM DUAL
)
SELECT dt,
season,
TO_CHAR(
FROM_TZ( CAST( dt AS TIMESTAMP ), 'UTC' )
AT TIME ZONE 'CET',
'YYYY-MM-DD HH24:MI:SS TZH:TZM TZR'
) AS cet_timezone
FROM dates;
01-AUG-2021 summer 2021-08-01 02:00:00 +02:00 CET
01-JAN-2021 winter 2021-01-01 01:00:00 +01:00 CET
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;
I have to calculate time difference in minutes from current(sysdate) and modified time:-
to_date(to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')
- to_date(to_char(modified, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')
but problem is to_char returns proper time:-
to_char(whenmodified, 'YYYY-MM-DD HH24:MI:SS')
Outputs 2016-05-23 14:55:50
and to_date doesn’t show time:-
to_date(to_char(modified, 'YYYY-MM-DD HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS')
Outputs: 2016-05-23
Please assist how I can get time difference by converting to_char to to_date.
NOTE:
I cant do sysdate-modified because both sysdate and modified gives date without time e.g 2016-05-23
Using to_char for sysdate or modified give date with time 2016-05-23 14:55:50
As we cant subtracts dates in to_char function I am again converting back them to to_date for getting time.
I am expecting:
2016-05-23 14:55:50 - 2016-05-23 14:53:50 = 2 min
I have to calculate time difference in minutes from current(sysdate) and modified time
Oracle Setup:
CREATE TABLE table_name ( modified DATE );
INSERT INTO table_name
SELECT TIMESTAMP '2016-05-23 14:20:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-05-23 00:00:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-05-01 00:00:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-01-01 00:00:00' FROM DUAL;
Query:
SELECT ( sysdate - modified ) * 24 * 60 AS minute_difference
FROM table_name;
Output:
MINUTE_DIFFERENCE
-----------------
3.66666667
863.666667
32543.6667
206783.667
And to address your comment that:
to_date doesn’t show time
A date always has a time component and never has a format internally to the database (it is represented by 7 or 8 bytes) - the formatting of a date is done by the client program that you use to access the database (and often the default is not to show the time component - however, the time component still exists).
You can change this either in the preferences of your client program or, if they don't use that to control it, by changing the NLS_DATE_FORMAT session parameter:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
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?
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;