Oracle Convert TIMESTAMP with Timezone to DATE - sql

I have DB with timezone +04:00 (Europe/Moscow) and need to convert a string in format YYYY-MM-DD"T"HH24:MI:SSTZH:TZM to DATE data type in Oracle 11g.
In other words, I have a string 2013-11-08T10:11:31+02:00 and I want to convert it to DATE data type (in local DB timezone +04:00 (Europe/Moscow)).
For string 2013-11-08T10:11:31+02:00 my desired transformation should return DATE data type with date 2013-11-08 12:11:31 (i.e. with local timezone transformation of time to +04:00 (Europe/Moscow)). Timezone of string may be different and +02:00 in string above is just example.
I tried to do this with TIMESTAMP data type, but no success with time zone transformation.

to_timestamp_tz() function with at time zone clause can be used to convert your string literal to a value of timestamp with time zone data type:
SQL> with t1(tm) as(
2 select '2013-11-08T10:11:31+02:00' from dual
3 )
4 select to_timestamp_tz(tm, 'yyyy-mm-dd"T"hh24:mi:ss TZH:TZM')
5 at time zone '+4:00' as this_way
6 , to_timestamp_tz(tm, 'yyyy-mm-dd"T"hh24:mi:ss TZH:TZM')
7 at time zone 'Europe/Moscow' as or_this_way
8 from t1
9 /
Result:
THIS_WAY OR_THIS_WAY
----------------------------------------------------------------------------
2013-11-08 12.11.31 PM +04:00 2013-11-08 12.11.31 PM EUROPE/MOSCOW
And then, we use cast() function to produce a value of date data type:
with t1(tm) as(
select '2013-11-08T10:11:31+02:00' from dual
)
select cast(to_timestamp_tz(tm, 'yyyy-mm-dd"T"hh24:mi:ss TZH:TZM')
at time zone '+4:00' as date) as this_way
, cast(to_timestamp_tz(tm, 'yyyy-mm-dd"T"hh24:mi:ss TZH:TZM')
at time zone 'Europe/Moscow' as date) as or_this_way
from t1
This_Way Or_This_Way
------------------------------------------
2013-11-08 12:11:31 2013-11-08 12:11:31
Find out more about at time zone clause and to_timestamp_tz() function.

SELECT
CAST((FROM_TZ(CAST(timezonefield AS TIMESTAMP),'GMT') AT TIME ZONE 'CET') AS DATE)
FROM table;
Converts a timestamp in GMT to date in Central European time

if you want your timestamp with timezone to convert to a date in sync with "sysdate" then use the following:
select cast(to_timestamp_tz('2013-11-08T10:11:31-02:00'
,'yyyy-mm-dd"T"hh24:mi:sstzh:tzm'
)
at time zone to_char(systimestamp
,'tzh:tzm'
)
as date
)
from dual

to cast time stamp to date :
cast(registrationmaster.Stamp5DateTime as date) >= '05-05-2018' AND
cast(registrationmaster.Stamp5DateTime as date) <= '05-05-2018'

you can manage timezones with CAST(x AT TIME ZONE 'YYYY' AS DATE), this helps me:
WITH t1 (tm) AS (SELECT TIMESTAMP '2021-12-14 15:33:00 EET' FROM DUAL)
SELECT 'EET' tz, CAST (tm AT TIME ZONE 'Europe/Kaliningrad' AS DATE) AS datetime FROM t1
union SELECT 'MSK' tz, CAST (tm AT TIME ZONE 'Europe/Moscow' AS DATE) AS datetime FROM t1
union SELECT 'CET' tz, CAST (tm AT TIME ZONE 'Europe/Prague' AS DATE) AS datetime FROM t1
union SELECT 'UTC' tz, CAST (tm AT TIME ZONE 'UTC' AS DATE) AS datetime FROM t1

Related

Need to simplify SQL query (Enter date at four locations)

I created a query which calculates the average of several sums over multiple tables. This needs to be run every week and how the code is made currently I need to change 4 dates in the query every time. I'm thinking this can be done more efficiently but i'm unsure how.
Select ROUND(
(Select sum (calls)
FROM (SELECT sum(ski.ANSTIME) AS calls
FROM SYNONYMS syn
JOIN SKILL ski on (syn.value = ski.split)
WHERE syn.ITEM_TYPE = 'split'
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(ski.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) >= '17-07-17 00:00:00 EUROPE/WARSAW' -- Date to be altered every week
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(ski.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) <= '24-07-17 00:00:00 EUROPE/WARSAW' -- Date to be altered every week
UNION ALL
SELECT sum(vdn.ANSTIME) AS calls
FROM SYNONYMS syn
JOIN VDN vdn on (syn.value = vdn.vdn)
WHERE syn.ITEM_TYPE = 'vdn'
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(vdn.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) >= '17-07-17 00:00:00 EUROPE/WARSAW' -- Date to be altered every week
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(vdn.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) <= '24-07-17 00:00:00 EUROPE/WARSAW')) -- Date to be altered every week
/ -- devided by
(SELECT sum (calltime)
FROM (SELECT sum(ski.acdcalls) AS calltime
FROM SYNONYMS syn
JOIN SKILL ski on (syn.value = ski.split)
WHERE syn.ITEM_TYPE = 'split'
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(ski.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) >= '17-07-17 00:00:00 EUROPE/WARSAW' -- Date to be altered every week
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(ski.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) <= '24-07-17 00:00:00 EUROPE/WARSAW' -- Date to be altered every week
UNION ALL
SELECT sum(vdn.acdcalls) AS calltime
FROM SYNONYMS syn
JOIN VDN vdn on (syn.value = vdn.vdn)
WHERE syn.ITEM_TYPE = 'vdn'
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(vdn.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) >= '17-07-17 00:00:00 EUROPE/WARSAW' -- Date to be altered every week
AND (SELECT (timestamp '1970-01-01 00:00:00 GMT' +numtodsinterval(vdn.starttime_utc, 'SECOND'))
at time zone 'Europe/Warsaw'
FROM dual) <= '24-07-17 00:00:00 EUROPE/WARSAW')) -- Date to be altered every week
,0) AS average
FROM dual
If I understand correctly you're trying to generate some weekly summary so instead of entering date you can try to use trunc(sysdate) for second date and trunc(sysdate - 7) for first.
Second possibility is to create temporary table (or just with statement) which will hold single date and join that to your query. Instead <= '24-07-17 00:00:00 EUROPE/WARSAW' you will have <= temp_date where temp_date comes from CTE.

Error in timestamp datatype

When I run the below query,
select timestamp '01-01-2017 00:00' log_time from dual
I get this error
ORA-01847: day of month must be between 1 and last day of month.
If it is not valid, How to declare timestamp datatype in oracle?
If you are using ANSI timestamp literals, the value must be formatted in the ISO style yyyy-mm-dd hh24:mi:ss:
select timestamp '2017-01-01 00:00:00' log_time
from dual;
Alternatively use Oracle's to_timestamp() function if you want to keep that format:
select to_timestamp('01-01-2017 00:00', 'dd-mm-yyyy hh24:mi') log_time
from dual

How to retrieve two country date/time using single query?

How to retrieve two different country date / time in single query? Whether I need to change any NLS parameters setting?
Sample query:
Select sysdate ind, sysdate us from dual;
O/p:
11/09/2015 3:05 PM 11/09/2015 05:35 AM
Try;
select systimestamp ind, systimestamp at time zone 'US/Eastern' us
from dual;
If you interested in date then;
select
cast(systimestamp as date) ind,
cast(systimestamp at time zone 'US/Eastern' as date) us
from dual;
Reference for all Time Zones
You can use FROM_TZ and TZ_OFFSET to get the same result:
select sysdate ind, FROM_TZ(TIMESTAMP '2015-09-11 15:50:42', TZ_OFFSET('US/Eastern')) us
from dual;
If you want to know more about the time zones then:
SELECT DISTINCT tzname
FROM V$TIMEZONE_NAMES;
Please refer these links for FROM_TZ and TZ_OFFSET
I think you can do it with the third noptions parameter of the to_char function.
It also seems that you can use the AT Timezone clause in your query
Here is an example given the link I gave (I am sorry I cannot test it for the moment):
SELECT FROM_TZ(CAST(TO_DATE('1999-12-01 11:00:00',
'YYYY-MM-DD HH:MI:SS') AS TIMESTAMP), 'America/New_York')
AT TIME ZONE 'America/Los_Angeles' "West Coast Time"
FROM DUAL;
You can use SYS_EXTRACT_UTC(SYSTIMESTAMP) to get the current Coordinated Universal Time and then:
India is 5½ Hours ahead of UTC;
US EST is 4 hours behind UTC; and
US PST is 7 hours behind UTC.
SQL Fiddle
Oracle 11g R2 Schema Setup:
Query 1:
SELECT TO_CHAR( SYS_EXTRACT_UTC(SYSTIMESTAMP), 'YYYY-MM-DD HH24:MI:SS.FF3' ) AS TIME_UTC,
TO_CHAR( SYS_EXTRACT_UTC(SYSTIMESTAMP) + INTERVAL '5' HOUR + INTERVAL '30' MINUTE, 'YYYY-MM-DD HH24:MI:SS.FF3' ) AS TIME_INDIA,
TO_CHAR( SYS_EXTRACT_UTC(SYSTIMESTAMP) - INTERVAL '4' HOUR, 'YYYY-MM-DD HH24:MI:SS.FF3' ) AS TIME_EST,
TO_CHAR( SYS_EXTRACT_UTC(SYSTIMESTAMP) - INTERVAL '7' HOUR, 'YYYY-MM-DD HH24:MI:SS.FF3' ) AS TIME_PST
FROM DUAL
Results:
| TIME_UTC | TIME_INDIA | TIME_EST | TIME_PST |
|-------------------------|-------------------------|-------------------------|-------------------------|
| 2015-09-11 10:04:22.482 | 2015-09-11 15:34:22.482 | 2015-09-11 06:04:22.482 | 2015-09-11 03:04:22.482 |

Oracle sql query to to obtain records for a date range in IST

I need to write sql query to obtain records for a date range in IST format.
We are storing data in the database in GMT format.
select *
from tableA a
where to_date(a.end_date,'DD-MON-YYYY') between date1 and date2;
(end_date is one of the column in tableA table)
Now date1 and date2 should fetch the records from database in IST time zone.
How i can write sql query for the above requirement.
Just Try the following query
SELECT FROM_TZ (
CAST (SYSDATE AS TIMESTAMP)--replace sysdate with your date column
, 'GMT'
)
AT TIME ZONE 'Asia/Calcutta'
FROM DUAL;
In My case timezone is CET , and there is 3.5 hour difference from INDIA
select systimestamp from dual
7/30/2013 4:24:10.379910 PM +02:001
SELECT FROM_TZ (
CAST (SYSDATE AS TIMESTAMP)--replace sysdate with your date column
, 'GMT'
)
AT TIME ZONE 'Asia/Calcutta'
FROM DUAL;
7/30/2013 7:54:10.000000 PM +05:30

Insert TIME into Oracle SQL, DATE field

Is there anyway to insert only time (no date) into a SQL field of type 'Date'
I have tried inserting:
13:00
and
01:00
and
13:00pm
and
01:00pm
But keep getting the error:
Not A Valid Month
The problem is the literal. For date/time values, Oracle expects values in the form ddMMMyyyy. (Or, you can use the expression DATE '2001-01-01. Literal values are explained here.) There doesn't appear to be a default format for time without a date.
In other words, you can get the same error with cast('1/1/2001' as date).
Instead, use the to_date() function:
select to_date('10:00', 'hh:mi')
from dual
This gives you much more flexibility with formats.
Also, as Ben notes in the comments, this gives you the current date with the time specified.
Example of using EXTRACT and time only portion of a SYSDATE and some date...:
SELECT hh||':'||mi||':'||ss time_only_portion
FROM
(
Select
EXTRACT(hour From Cast(SYSDATE as timestamp)) hh,
EXTRACT(minute From Cast(SYSDATE as timestamp)) mi,
EXTRACT(second From Cast(SYSDATE as timestamp)) ss
From dual
)
/
SELECT EXTRACT(HOUR From t_stamp) hh
FROM
(
SELECT CAST(to_date('21/02/2012 06:10:00 am', 'dd/mm/yyyy hh:mi:ss am') AS TIMESTAMP) t_stamp
FROM dual
)
/