I've faced today a weird problem: I have a function which is called by job. I want to find the difference from start of the function till the end to log it then to some table.
So, let's say I have function
procedure p is
starttime timestamp := systimestamp;
procedure writeTime
is
diff interval day to second := systimestamp - starttime;
begin
-- here insert diff to some table
end;
begin
-- doing some long stuff
writeTime();
exception
when others then
writeTime();
end;
The problem in the function is:
When I run this manually, it works well, difference is clear. E.g. I use extract to parse the interval: extract(hour from diff)*60*60 + extract(minute from diff)*60 + extract(second from diff)
When I set up the job and the job runs this function I have a big problem: it returns negative result, which as I, after some tests, understand is generated here systimestamp - starttime
. Seems like systimestamp in this calculation is taken from Greenwich timezone, and mine is one hour bigger, so this calculation diff interval day to second := systimestamp - starttime;
is returning the value like (-1 hour + difference).
By stupid brute-forcing I've found a solution:
procedure p is
starttime timestamp := systimestamp;
procedure writeTime
is
diff interval day to second;
endtime timestamp := systimestamp;
begin
diff := endtime - starttime;
-- here insert diff to some table
end;
begin
-- doing some long stuff
writeTime();
exception
when others then
writeTime();
end;
which simply writes systimestamp in the variable first, and only then calculates the difference.
My database parameters:
So now the question: I really want to know is it a bug of my RDBMS or perhaps I do not see some obvious explanation why it is like that? The concrete question is: why during this operation
starttime timestamp := systimestamp;
it takes one timezone and during this
diff interval day to second := systimestamp - starttime;
it takes another one in the same procedure of the same session with the same settings?
Is the database timezone DBTIMEZONE
the same like your session timezone SESSIONTIMEZONE
?
Function SYSTIMESTAMP
returns datatye TIMESTAMP WITH TIME ZONE
, so you do an implicit convertion into TIMESTAMP
datatype.
Datatype of LOCALTIMESTAMP
is TIMESTAMP
.
Try
starttime timestamp WITH TIME ZONE := systimestamp;
or
starttime timestamp := LOCALTIMESTAMP;
You can check with this query in which timezone the Schedule Jobs are running:
SELECT * FROM ALL_SCHEDULER_GLOBAL_ATTRIBUTE where attribute_name = 'DEFAULT_TIMEZONE'