ORACLE Casting DATE to TIMESTAMP WITH TIME ZONE WITH OFFSET - sql

I need to cast a DATE value in a query to a TIMESTAMP WITH TIME ZONE, but currently I'm getting the TimeZone Region ('Europe / Paris') which is not valid to be used by EF.
For example, when doing this:
select CAST(FECHA AS TIMESTAMP WITH TIME ZONE) from test;
I currently get this output:
07/03/14 09:22:00,000000000 EUROPE/PARIS
But I need it to be like:
07/03/14 09:22:00,000000000 +01:00
Any idea how to accomplish this?

You can cast the DATE to a TIMESTAMP, then use FROM_TZ to convert this timestamp to a timestamp with time zone:
SQL> SELECT from_tz(CAST (SYSDATE AS TIMESTAMP), '+01:00') tz FROM dual;
TZ
-------------------------------------------------
07/03/14 09:47:06,000000 +01:00

With #Vincent Malgrat solution you need to get the TIMEZONE_HOUR and then, format it to use in your query. I don't know if there is any chance to make it automatically.
I can suggest you to nest some functions. It is not the cleanest solution but it works for me
SELECT TO_TIMESTAMP_TZ(TO_CHAR(CAST(FECHAHORA AS TIMESTAMP WITH TIME ZONE), 'DD-MM-YY HH24:MI:SS TZH:TZM'), 'DD-MM-YY HH24:MI:SS TZH:TZM' )FROM TEST;
And the result will be something like
03/03/14 09:58:02,000000000 +01:00
Regards!

Use
ALTER SESSION SET TIME_ZONE = '+01:00';
before your SELECT

Related

Casting Local Time to UTC Formating Incorrect

HIRE_DATE is in a 'DATE' column. The timestamp is local (Los Angeles); I would like to convert it to UTC.
I can't for the life of me fathom why the UTC output is mangled (Last 2 digits of YY is the DD; and vice-versa) -- and the time does not convert to UTC.
HIRE_DATE: 30/04/2019 12:00:00 AM
select from_tz(to_timestamp(HIRE_DATE,'DD-MM-YY HH24:MI:SS'), 'America/Los_Angeles') at time zone 'UTC' from TABLE
OUTPUT: 19/04/2030 12:00:00 AM
If HIRE_DATE is a DATE data type then you don't need TO_TIMESTAMP.
TO_TIMESTAMP is used to convert a string (i.e. VARCHAR2) into a TIMESTAMP value but you have a DATE value.
Just do
select from_tz(CAST(HIRE_DATE AS TIMESTAMP), 'America/Los_Angeles') at time zone 'UTC'
from TABLE
Actually I don't understand why FROM_TZ does not accept DATE values whereas almost any other date/timestamp related function accept either DATE or TIMESTAMP value as input.
Note, the default output display format of this query is defined by current user session NLS_TIMESTAMP_TZ_FORMAT setting. If you are not satisfied with the output format, either change NLS_TIMESTAMP_TZ_FORMAT setting by executing ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = '...' or use TO_CHAR function to set output format explicitly.
Instead of
... AT TIME ZONE 'UTC'
you can also use
SYS_EXTRACT_UTC(...)
The upper returns a TIMESTAMP WITH TIME ZONE value, the second one returns a TIMESTAMP value.
Would this do any good?
SQL> select from_tz(cast (sysdate as timestamp), 'UTC') result from dual;
RESULT
---------------------------------------------------------------------------
27.09.20 10:59:28,000000 UTC
Or, in your case
select from_tz(cast (hire_date as timestamp), 'UTC' from dual
No need to apply any format mask to hire_date as it is a DATE datatype (at least, that's what you said).
You use the word "convert" which can mean one of two things:
change the data type, which is what FROM_TZ does
change the value from one time zone to another, which FROM_TZ does not do.
You didn't give your expected output, so we may misunderstand.
To change the data type:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select from_tz(cast(dte as timestamp), 'America/Los_Angeles') from data
FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES')
30-APR-19 12.00.00.000000 PM AMERICA/LOS_ANGELES
To get the simultaneous datetime value in UTC:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select cast(sys_extract_utc(from_tz(cast(dte as timestamp), 'America/Los_Angeles')) as date) from data
CAST(SYS_EXTRACT_UTC(FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES'))ASDATE)
2019-04-30 19:00:00

How to convert timezone of date type variable in oracle trigger

If I have date type variable
date_time date := sysdate; -- Suppose the timezone is EST.
Now, How I can convert the timezone of variable to UTC?
You can try this:
SELECT SYSTIMESTAMP at time zone 'UTC' FROM DUAL;
Its not very clear from your question what exactly you require but if I understood correctly you require time in UTC
SELECT CAST(sys_extract_utc(SYSTIMESTAMP) AS TIME) FROM DUAL;

Convert datetime column to utc time

I would like to achieve the following.
I have a datetime column that i calculated with the following functions.
to_char(to_date(f_sta_date, 'YYYYMMDD') + (f_sta_time)/86400), 'YYYY-MM-DD HH24:MI:SS')
to_char(to_date(f_sta_date, 'YYYYMMDD') + (f_sta_time)/86400), 'YYYY-MM-DD HH24:MI:SS')
T1
f_sta_date f__sta_time f_sto_date f_sto_time DT_sta DT_sto
20191001 6689 20191001 7185 2019-10-01 01:54:49 2019-10-01 01:59:45
Desired table
T1
f_sta_date f_sta_time_id f_sto_date f_sto_time_id DT_sta DT_sto DT_sta_UTC DT_sto_UTC
20191001 6689 20191001 7185 2019-10-01 01:54:49 2019-10-01 01:59:45
What function could i add to the functions above to achieve the desired result?
To start with: to_char() returns a string from a date. So if you want a date, don't use it, ie replace this:
to_char(to_date(f_sta_date, 'YYYYMMDD') + (f_sta_time)/86400), 'YYYY-MM-DD HH24:MI:SS')
To:
to_date(f_sta_date, 'YYYYMMDD') + f_sta_time/86400
Then: when it comes to managing timezones, you need to use the timestamp with time zone datatype instead of date. To convert your date in localtime (ie the time zone of your session, that is defined by SESSIONTIMEZONE) to a timestamp and get the corresponding date/time at UTC, you can do:
cast(to_date(f_sta_date, 'YYYYMMDD') + f_sta_time/86400 as timestamp with time zone)
at time zone 'UTC'
Your query:
select
to_date(f_sta_date, 'YYYYMMDD') + f_sta_time/86400 dt_sta,
to_date(f_sto_date, 'YYYYMMDD') + f_sto_time/86400 dt_sto,
cast(to_date(f_sta_date, 'YYYYMMDD') + f_sta_time/86400 as timestamp)
at time zone 'UTC' dt_sta_utc,
cast(to_date(f_sto_date, 'YYYYMMDD') + f_sto_time/86400 as timestamp)
at time zone 'UTC' dt_sto_utc
from t
From the discussion in comments under your post, it appears that your date-time (which you are already able to calculate) should instead be a timestamp with time zone, specifically "at time zone CET". Perhaps for your purposes date with time zone would suffice (in Oracle, "date" always means date-time); alas, Oracle doesn't have such a data type, we must use timestamp with time zone.
Below I show how to calculate that, in the WITH clause. (Note that I use a different approach for computing even the date-time - I convert your "time" component to seconds directly, using the Oracle function specifically designed for that, instead of arithmetic operations. Also, while Oracle usually allows you to use a number - your date component - as if it were a string, in some cases it doesn't. For example, you can do that in TO_DATE, but you can't in TO_TIMESTAMP. In any case, you should never rely on such implicit conversions; always make them explicit in your code.)
I show how I created the table for testing; then, in the query, in the WITH clause I do a preliminary computation (computing your DT_STA and DT_STO, but as timestamps with time zone); then in the main query I show how to convert to a different time zone.
create table t1 (
f_sta_date number,
f_sta_time number,
f_sto_date number,
f_sto_time number
);
insert into t1 values (20191001, 6689, 20191001, 7185);
commit;
with
prep (f_sta_date, f_sta_time, f_sto_date, f_sto_time, dt_sta, dt_sto) as (
select f_sta_date, f_sta_time, f_sto_date, f_sto_time,
from_tz(to_timestamp(to_char(f_sta_date), 'yyyymmdd')
+ numtodsinterval(f_sta_time, 'second'), 'CET'),
from_tz(to_timestamp(to_char(f_sto_date), 'yyyymmdd')
+ numtodsinterval(f_sto_time, 'second'), 'CET')
from t1
)
select f_sta_date, f_sta_time, f_sto_date, f_sto_time, dt_sta, dt_sto,
dt_sta at time zone 'UTC' as dt_sta_utc,
dt_sto at time zone 'UTC' as dt_sto_utc
from prep
;
F_STA_DATE F_STA_TIME F_STO_DATE F_STO_TIME DT_STA DT_STO DT_STA_UTC DT_STO_UTC
---------- ---------- ---------- ---------- ----------------------- ----------------------- ----------------------- -----------------------
20191001 6689 20191001 7185 2019-10-01 01:51:29 CET 2019-10-01 01:59:45 CET 2019-09-30 23:51:29 UTC 2019-09-30 23:59:45 UTC

What is the proper way of formatting date in select query Oracle SQL

For suppose if I want sysdate,
SELECT SYSDATE as system_date FROM DUAL;
should output in the following format
14-Feb-2018 T19:50:02+00:00
i.e.,
DD-MMM-YYYY Thh:mm:ss+HH:MM
Assuming you know the date represents UTC and want the +00:00 part to be fixed:
select to_char(sysdate, 'DD-Mon-YYYY "T"HH24:MI:SS"+00:00"') from dual;
TO_CHAR(SYSDATE,'DD-MON-YYYY"T"HH24:
------------------------------------
14-Feb-2018 T20:13:08+00:00
The format model elements are in the documentation. That includes a section on character literals, which I've used for the fixed T and +00:00 parts.
As #mathguy said, this seems a bit unusual; and you might actually to leave the column as a native date and have your application or reporting tool or whatever format it for you. It depends what exactly you're doing, and whether you actually want a string value directly from the query.
As your updated question now doesn't have that pseudo-timezone, it's now even simpler, but the same idea:
select to_char(sysdate, 'DD-Mon-YYYY "T"HH24:MI:SS') from dual;
TO_CHAR(SYSDATE,'DD-MON-YYYY"T
------------------------------
14-Feb-2018 T20:17:50
If you're working with a data type that knows about time zones - i.e. not a plain DATE or TIMESTAMP - you can include those in the formatting using the appropriate model elements:
select to_char(systimestamp, 'DD-Mon-YYYY "T"HH24:MI:SSTZH:TZM') from dual;
TO_CHAR(SYSTIMESTAMP,'DD-MON-YYYY"T"
------------------------------------
14-Feb-2018 T20:24:58+00:00
which happens to still show +00:00 because my system is in the UK. With a different value it shows something appropriate:
alter session set time_zone = 'AMERICA/NEW_YORK';
select to_char(current_timestamp, 'DD-Mon-YYYY "T"HH24:MI:SSTZH:TZM') from dual;
TO_CHAR(CURRENT_TIMESTAMP,'DD-MON-YY
------------------------------------
14-Feb-2018 T15:28:57-05:00
Notice now I'm using systimestamp and current_timestamp, which are TZ-aware, and not sysdate or current_date which are not - you'l get an error if you try to get the TZH or TZM elements from those.
The format you are requesting doesn't make much sense. +00:00 is the time zone offset (otherwise what is it?) but in Oracle the DATE data type does not know about time zones. Only the Oracle data type TIMESTAMP WITH TIME ZONE should be formatted that way in Oracle.
Here is how this should be done with timestamps WITH TIME ZONE. Note that the standard SYSTIMESTAMP function is a timestamp WITH TIME ZONE. In the query below, you can see how the timestamp is formatted using my session's default, and then using an explicit format model.
SQL> select systimestamp,
2 to_char(systimestamp, 'dd-Mon-yyyy "T"hh24:mi:sstzh:tzm') as ts
3 from dual
4 ;
SYSTIMESTAMP TS
------------------------------------------- ---------------------------
14-FEB-18 12.14.18.537000 PM -08:00 14-Feb-2018 T12:14:18-08:00

How to convert timestamps' timezones in order to compare them in Oracle DB?

We are using Oracle 11g and we have a table with a timestamp column which doesn't contain the timezone (simply defined as TIMESTAMP). The timezone is written in a different column.
I want to be able to use the 'max' function while taking the timezone into account.
There's probably a function to convert timezones easily and I just don't know it.
I want to be able to do something like this:
SELECT max(covert_to_timezone(my_timestamp, my_timezone, 'GMT')) FROM my_table
How can I do that?
==================
Solution: According to Ajith Sasidharan's answer:
SELECT max(from_tz(my_timestamp, my_timezone) at time zone '0:00') FROM my_table
Update: If you want to compare dates, simply use 'cast':
SELECT max(from_tz(cast(my_date as timestamp), my_timezone) at time zone '0:00') FROM my_table
Btw, now I got 'ORA 01878' errors, meaning our table contains invalid times (DST shit).
I guess you want a function like this ::
select to_char((from_tz(to_timestamp(to_char(DATABASE_DATE, 'YYYY-MM-DD HH:MI:SS PM'), 'YYYY-MM-DD HH:MI:SS PM') ,'America/New_York')
at time zone 'America/Los_Angeles'),'YYYY-MM-DD HH:MI:SS PM TZD') as localtime
from table