Oracle timestamp and Interval - oracle

I have a requirement to get records from a table that are systimestamp > LAST_UPDATE_TS + 5 minutes interval
Could you please help with query?
ORACLE DB - 11G Version.
I have tried this as below but not working as expected.
SYSTIMESTAMP : 11-MAR-20 06.06.00.070695 AM -05:00
LAST_UPDATE_TS : 11-MAR-20 06.05.50.781167 AM
After applying this condition, systimestamp > LAST_UPDATE_TS + INTERVAL '5' MINUTE,
I expect no data should return, but still i get rows that doesn't satisfy condition.

You are comparing SYSTIMESTAMP which is a TIMESTAMP WITH TIME ZONE data type to a TIMESTAMP(6) data type; this requires a conversion to a time zone.
If you use:
SELECT SESSIONTIMEZONE FROM DUAL;
The you can see the time zone your session is using.
On db<>fiddle, the default is UTC (+00:00) and running:
SELECT DUMMY AS query1
FROM DUAL
WHERE TIMESTAMP '2020-03-11 06:06:00.070695 -05:00' > TIMESTAMP '2020-03-11 06:05:50.781167' + INTERVAL '5' MINUTE
Outputs:
| QUERY1 |
| :----- |
| X |
Since 2020-03-11 06:06:00.070695 -05:00 is greater than 2020-03-11 06:10:50.781167 +00:00.
If you change the session time zone:
ALTER SESSION SET TIME_ZONE = '-05:00';
and run the same query again (a different column alias was used to prevent caching):
SELECT DUMMY AS query2
FROM DUAL
WHERE TIMESTAMP '2020-03-11 06:06:00.070695 -05:00' > TIMESTAMP '2020-03-11 06:05:50.781167' + INTERVAL '5' MINUTE
Then the output has zero rows:
| QUERY2 |
| :----- |
If you want to manually set the timezone in the conversion then you can use the FROM_TZ function:
SELECT DUMMY AS query3
FROM DUAL
WHERE TIMESTAMP '2020-03-11 06:06:00.070695 -05:00' > FROM_TZ( TIMESTAMP '2020-03-11 06:05:50.781167', '-05:00' ) + INTERVAL '5' MINUTE
Which, again, outputs zero rows:
| QUERY3 |
| :----- |
db<>fiddle here

SYSTIMESTAMP returns a TIMESTAMP WITH TIME ZONE value which is compared with a TIMESTAMP value.
Actually Oracle is doing this:
SYSTIMESTAMP > FROM_TZ(LAST_UPDATE_TS + INTERVAL '5' MINUTE, SESSIONTIMEZONE)
Comparison itself is performed on UTC times.
SYSTIMESTAMP is returned in the time zone of database server's operating system. If this time zone is equal to your current SESSIONTIMEZONE then the condition works as expected.
Either change your session time zone to the time zone of database server's operating system or try this one:
LOCALTIMESTAMP > LAST_UPDATE_TS + INTERVAL '5' MINUTE
which does not utilize time zones at all.

After checking few forums and other stackoverflow pages, I tried this and it seams to be working now.
select *
from table
where cast(systimestamp as TIMESTAMP) > (lst_updt_ts + interval '3' minute);

Doing it the old way?
systimestamp -5/(60*24) > LAST_UPDATE_TS

Related

Converting TIMESTAMP to DATE with respect to timezone

I was inspecting how are DATEs stored in database. Consider the following statement:
SELECT
CAST (to_timestamp_tz('2018-12-05T10:00:00+01:00', 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM') AS DATE) AS PRAGUE_TIME,
CAST (to_timestamp_tz('2018-12-05T10:00:00+00:00', 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM') AS DATE) AS GMT_TIME
FROM DUAL
Results in:
PRAGUE_TIME GMT_TIME
2018-12-05 10:00:00 2018-12-05 10:00:00
The times are the same, despite one being created from a +1 timezone offset. Just to be sure, I added further conversion to string:
SELECT
TO_CHAR(CAST (to_timestamp_tz('2018-12-05T10:00:00+01:00', 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM') AS DATE),'YYYY-MM-DD HH24:MI:SS') AS PRAGUE_TIME,
TO_CHAR(CAST (to_timestamp_tz('2018-12-05T10:00:00+00:00', 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM') AS DATE),'YYYY-MM-DD HH24:MI:SS') AS GMT_TIME
FROM DUAL
PRAGUE_TIME GMT_TIME
2018-12-05 10:00:00 2018-12-05 10:00:00
Same results. So how can I convert TIMESTAMP to DATE without loosing the timezone information?
how can I convert TIMESTAMP to DATE without loosing the timezone information?
You cannot.
A DATE only has year, month, day, hour, minute and second components.
A TIMESTAMP has all those components plus nanoseconds and optionally time zone or time zone offset components.
If you convert from a TIMESTAMP to a DATE then you will lose the information that the DATE cannot store.
What you can do is convert all the TIMESTAMPs to the same time zone using, for example, AT TIME ZONE 'UTC':
SELECT CAST( TIMESTAMP '2018-12-05 10:00:00+01:00' AT TIME ZONE 'UTC' AS DATE )
AS PRAGUE_TIME_AS_UTC,
CAST( TIMESTAMP '2018-12-05 10:00:00+00:00' AT TIME ZONE 'UTC' AS DATE )
AS GMT_TIME_AS_UTC
FROM DUAL
Results:
| PRAGUE_TIME_AS_UTC | GMT_TIME_AS_UTC |
|----------------------|----------------------|
| 2018-12-05T09:00:00Z | 2018-12-05T10:00:00Z |

Convert epoch to date in Oracle

Was wondering if anyone could help with precision time conversion.
Sample: 1501646399999 which is GMT: Wednesday, August 2, 2017 3:59:59.999 AM
I used the below query, but it always rounds off to 02-AUG-17 04:00:00. Can anyone please guide me
select TO_TIMESTAMP('1970-01-01 00:00:00.000', 'YYYY-MM-DD hh24:mi:SS.FF3') + ((1/86400000) * 1501646399999)
from dual;
The problem is that you're adding a number to your fixed timestamp, which is causing that timestamp to be implicitly converted to a date - which doesn't have sub-second precision.
If you add an interval instead then it stays as a timestamp:
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3';
select TO_TIMESTAMP('1970-01-01 00:00:00.000', 'YYYY-MM-DD hh24:mi:SS.FF3')
+ numtodsinterval(1501646399999/1000, 'SECOND')
from dual;
TO_TIMESTAMP('1970-01-0
-----------------------
2017-08-02 03:59:59.999
Incidentally, you could slightly simplify your query with a timestamp literal:
select TIMESTAMP '1970-01-01 00:00:00' + numtodsinterval(...)
You may also want to check if you should be declaring that timestamp as being UTC, and converting back to local time zone after adding the epoch value; or leaving it explicitly as UTC but as a timestamp with time zone value. It depends exactly what that number is supposed to represent. (You said it's GMT/UTC, but still...)

How to Add an Interval to a Date in Oracle

I'm trying to get a new date from the product of 'date' + 'time interval'.
Something like this.
'15/02/2016 18:00:00' + '+00 02:00:00.000000'
Expected result:
'15/02/2016 20:00:00'
But using the columns in database.
CREATE TABLE timerest
(
DATE_ASIGN DATE,
TIME_ASIGN INTERVAL DAY(2) TO SECOND(0)
);
Thanks for your help.
You can just add them together:
insert into timerest (date_asign, time_asign)
values (to_date('15/02/2016 18:00:00', 'DD/MM/YYYY HH24:MI:SS'),
to_dsinterval('+00 02:00:00.000000'));
alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI:SS';
select date_asign + time_asign from timerest;
DATE_ASIGN+TIME_ASIGN
---------------------
15/02/2016 20:00:00
This follows the rules for datetime/interval arithmetic: date + interval = date.
If you have a date in DATE format you can simply add the a numeric interval that represents days (for example 1.5 is 1 day and a half)
You can extract from the time interval days and hours and then add them to to you date because, if I remember correctly, you can't add directly them to a date type (maybe to a timestamp type you can)
To extract the days you can use the extract function:
(
extract(second from TIME_ASIGN)/3600)+(extract(hour from TIME_ASIGN)/24)+(extract(day from TIME_ASIGN)/24)
then you add the number to your DATE_ASIGN

Converting a stored UTC time in Oracle 10g to local time

I have a varchar2(20) column with a value like '2015-01-26T20:29:51Z'.
I successfully convert it to a date with to_date(dEnteredDate,'YYYY-MM-DD"T"HH24:MI:SS"Z"')
I wish to convert it to local time by subtracting my SessionTimeZone, currently -07:00 and have a regular date with time, no timezone info.
I do this in MS SQL with;
SET #diff = datediff(hh,GetUTCDate(), GetDate());
SET #dlocal = DATEADD(hh, #diff, #UTCDateTime)
How can I accomplish the same in Oracle 10g?
You can do it like this:
select to_timestamp(dEnteredDate,'YYYY-MM-DD"T"HH24:MI:SS"Z"')- interval '7' hour from test_3;
Here - interval '7' hour will subtract the required time difference and give you the desired result without timezone.
You can do it like this
select cast(to_timestamp_TZ(dEnteredDate||' UTC','YYYY-MM-DD"T"HH24:MI:SS"Z" tzr') at local as date)
from ...

Oracle current_timestamp to seconds conversion

We are using Oracle database.
In our table timestamp is stored as seconds since 1970, how can I convert the time stamp obtained through current_timestamp() function to seconds
This would do it:
select round((cast(current_timestamp as date) - date '1970-01-01')*24*60*60) from dual
Though I wouldn't use current_timestamp if I was only interested in seconds, I would use SYSDATE:
select round((SYSDATE - date '1970-01-01')*24*60*60) from dual
Maybe not completely relevant. I had to resolve other way around problem (e.g. Oracle stores timestamp in V$RMAN_STATUS and V$RMAN_OUTPUT) and I had to convert that to date/timestamp. I was surprised, but the magic date is not 1970-01-01 there, but 1987-07-07. I looked at Oracle's history and the closest date I can think of is when they ported Oracle products to UNIX. Is this right?
Here's my SQL
SELECT /*+ rule */
to_char(min(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON-YYYY HH24:MI:SS') start_tm
, to_char(to_char(max(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON HH24:MI:SS')) end_tm
FROM V$RMAN_STATUS
START WITH (RECID, STAMP) =
(SELECT MAX(session_recid),MAX(session_stamp) FROM V$RMAN_OUTPUT)
CONNECT BY PRIOR RECID = parent_recid ;
I needed to send timestamp to GrayLog via GELF from Oracle DB. I tried different versions and solutions but only one worked correctly.
SQL:
SELECT REPLACE((CAST(dat AS DATE) - TO_DATE('19700101', 'YYYYMMDD')) * 86400 + MOD(EXTRACT(SECOND FROM dat), 1), ',', '.') AS millis
FROM (SELECT SYSTIMESTAMP AT TIME ZONE 'GMT' AS dat FROM dual)
The result for Systmiestamp
2018/12/18 19:47:29,080988 +02:00
will be
1545155249.080988

Resources