How to get UTC value for SYSDATE on Oracle - oracle

Probably a classic... Would you know a easy trick to retrieve an UTC value of SYSDATE on Oracle (best would be getting something working on the 8th version as well).
For now I've custom function :(
Cheers,
Stefan

You can use
SELECT SYS_EXTRACT_UTC(TIMESTAMP '2000-03-28 11:30:00.00 -02:00') FROM DUAL;
You may also need to change your timezone
ALTER SESSION SET TIME_ZONE = 'Europe/Berlin';
Or read it
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM dual;

select sys_extract_utc(systimestamp) from dual;
Won't work on Oracle 8, though.

Usually, I work with DATE columns, not the larger but more precise TIMESTAMP used by some answers.
The following will return the current UTC date as just that -- a DATE.
CAST(sys_extract_utc(SYSTIMESTAMP) AS DATE)
I often store dates like this, usually with the field name ending in _UTC to make it clear for the developer. This allows me to avoid the complexity of time zones until last-minute conversion by the user's client. Oracle can store time zone detail with some data types, but those types require more table space than DATE, and knowledge of the original time zone is not always required.

I'm using:
SELECT CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE) FROM DUAL;
It's working fine for me.

If you want a timestamp instead of just a date with sysdate, you can specify a timezone using systimestamp:
select systimestamp at time zone 'UTC' from dual
outputs: 29-AUG-17 06.51.14.781998000 PM UTC

Related

Oracle timezone offset differs when run in sqlplus vs sql developer

Here's a puzzler. Take the following query and execute in oracle sqldeveloper:
select to_char(CAST (sysdate AS TIMESTAMP WITH TIME ZONE) ,'TZH:TZM') dst,
to_char(CAST (sysdate-160 AS TIMESTAMP WITH TIME ZONE) ,'TZH:TZM') nodst
from dual;
you will get the results of "-04:00", "-05:00". This gives the correct dst-adjusted timezone offset (eastern) with one date in dst, and the other not. Running the same query from sqlplus gives both values as "-4:00". This is causing a problem for a package that when called from sqlplus shows the incorrect value also.
When you cast to a timestamp with time zone, Oracle has to choose which time zone to use; and it uses the current session time zone. It's equivalent to doing:
select to_char(FROM_TZ(CAST (sysdate AS TIMESTAMP), SESSIONTIMEZONE) ,'TZH:TZM') dst,
to_char(FROM_TZ(CAST(sysdate-160 AS TIMESTAMP), SESSIONTIMEZONE) ,'TZH:TZM') nodst
from dual;
As you are getting different results in SQL Developer and SQL*Plus, you seem to have different session time zones in those two clients. You can check by querying sessiontimezone in each. SQL Developer sets the session time zone from the Java time zone (picked up from the operating system by default; you can override that by passing a user.timezone value at start-up). SQL*Plus uses the ORA_SDTZ environment variable, so you can set that to match your locale if you don't want to set it from within the database with alter session (manually or via login.sql); and if unset it defaults to 'OS_TZ':
The default value of the ORA_SDTZ variable, which is used when the variable is not set or it is set to an invalid value, is 'OS_TZ'.
... and it's picking that up as an offset (-04:00) rather than a region.
If you always want the result to be in a particular time zone regardless of any user's session settings, then you can state which one to use instead, e.g.:
select to_char(FROM_TZ(CAST (sysdate AS TIMESTAMP), 'America/New_York') ,'TZH:TZM') dst,
to_char(FROM_TZ(CAST(sysdate-160 AS TIMESTAMP), 'America/New_York') ,'TZH:TZM') nodst
from dual;
db<>fiddle with several session settings to demonstrate.
Presumably your real query is working from a variable date value, not sysdate; otherwise you could use systimestamp instead, with at time zone to adjust to a different zone if necessary.
This gives the correct dst-adjusted timezone offset (eastern) with one date in dst, and the other not.
No, it gives you a manually adjusted value that appears to be correct; however, when DST ends then your query will be incorrect and it will require adjusting ... then next spring it will require adjusting again ... and next autumn.
If you want the correct values then let Oracle adjust the time zones (and you don't need to cast SYSDATE to a TIMESTAMP WITH TIME ZONE, you can just use SYSTIMESTAMP or CURRENT_TIMESTAMP):
SELECT TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'US/Eastern', 'TZH:TZM')
AS timezone
FROM DUAL

Oracle server timezone using SQL query

I ran
select SYSDATE from dual;
Output:
SYSDATE |
-------------------|
2019-10-09 08:55:29|
Then I ran,
SELECT DBTIMEZONE FROM DUAL;
Output:
DBTIMEZONE|
----------|
+00:00 |
In the first output, time is in EST and 2nd output suggests timezone is UTC.
How do I check oracle server timezone via SQL query?
From the docs:
The database time zone [DBTIMEZONE] is relevant only for TIMESTAMP WITH LOCAL TIME ZONE columns. Oracle recommends that you set the database time zone to UTC (0:00)...
SYSDATE/SYSTIMESTAMP will return the time in the database server's OS timezone. Selecting a TIMESTAMP WITH LOCAL TIME ZONE datatype will return the time in your session's timezone (ie, SESSIONTIMEZONE).
select
CAST(systimestamp AS timestamp(0) with local time zone) as local_time,
systimestamp as server_time
from dual;
DBTIMEZONE is only used as the base timezone stored in TIMESTAMP WITH LOCAL TIME ZONE columns - which you never see, because when you select from one of those columns it gets translated into your session timezone.
See this similar question for a very detailed answer.
It is a common misunderstanding that SYSDATE or SYSTIMESTAMP are returned at DBTIMEZONE
SYSDATE and SYSTIMESTAMP are given in the time zone of database server's operating system. If you like to interrogate the time zone of database server's operating system run
SELECT TO_CHAR(SYSTIMESTAMP, 'tzr') FROM dual;
see also How to handle Day Light Saving in Oracle database

Why do oracle triggers show a different timestamp what is being inserted

My table has a Trigger that stores current_timestamp into a field when the row in the table is updated.
When a row is first inserted it is inserted with a Created date equal to Current_Timestamp. It appears when the procedure inserts the created_date it is given the correct time for daylight savings time but the trigger is inserting the incorrect time.
So the records in question are showing a created date of '2018-03-11 03:13:53.392086000' and a modified date of '2018-03-11 02:13:53.392086000'.
To add to this, we use goldengate for replication and it is using '2018-03-11 03:13:53.392086000' as the audit timestamp and not '2018-03-11 02:13:53.392086000'
Why would a trigger show a time differently then goldengate and the insert? database version I am working with is Oracle 11.2.0.4.0.
Trigger that handles the insert modified time
create or replace trigger UT_INSERT before insert on MYTABLE
REFERENCING NEW AS NEWROW OLD AS OLDROW FOR EACH ROW
begin
:NEWROW.MODIFIED_TIMESTAMP := CURRENT_TIMESTAMP;
end;
Trigger for updated modified time
create or replace trigger UT_UPDATE before update on MYTABLE
REFERENCING NEW AS NEWROW OLD AS OLDROW FOR EACH ROW
begin
:NEWROW.MODIFIED_TIMESTAMP := CURRENT_TIMESTAMP;
end;
The insert statement that is setting created_date is using Current_timestamp. All sessions are currently using a TZ offset of -05:00 and the sessiontimezone is America/Chicago.
That can't always be true. The only way to get the two values you have is for the insert to have been done with created_date set to systimestamp and for the session that issued that to have had it's session time zone set to -05:00, not to America/Chicago.
The reason that must be the case is that there was no 02:13 on March 11th because of the DST change:
select timestamp '2018-03-11 03:13:53.392086000 America/Chicago' from dual;
TIMESTAMP'2018-03-1103:13:53.392086000AMERICA
---------------------------------------------
2018-03-11 03:13:53.392086000 AMERICA/CHICAGO
select timestamp '2018-03-11 02:13:53.392086000 America/Chicago' from dual;
Error report -
SQL Error: ORA-01878: specified field not found in datetime or interval
01878. 00000 - "specified field not found in datetime or interval"
select timestamp '2018-03-11 02:13:53.392086000 -5:00' from dual;
TIMESTAMP'2018-03-1102:13:53.3920860
------------------------------------
2018-03-11 02:13:53.392086000 -05:00
So assuming the column value was set from your trigger, which seems entirely reasonable, the session which did that must have been -05:00 to be able to have got the timestamp at 02:13; and the created_date must have been using systimestamp, where the server OS had the correct time zone of America/Chicago to pick up the DST change (ignore dbtimezone for this), to have got 03:13 at the same moment in time.
As long as the session time zone and server time zone are the same you won't see a discrepancy between using current_timestamp or systimestamp, but you can't always control how sessions are configured, so a mistake or deliberate time zone change can cause problems like this.
Unless you are specifically trying to record a user's local time for some reason (and then you should probably be using a timestamp data type that preserves the time zone), it's safer to always use systimestamp for all of the values you record; and if you're storing as a plain timestamp then it might be safer to always store UTC time.
(Changing to UTC now, particularly with existing data to worry about, probably isn't an option; and not sure how Golden Gate would handle that but seems like a common scenario. Something to think about for the future though. Changing to always use systimestamp ought to be fairly transparent, except that you have this and probably other discrepancies to worry about. Finding and changing all code that might do inserts could be an issue - but then you seem to have inconsistencies already).

How to change the value of the default systimestamp in oracle

Is there a way to change the value of the default timestamp in oracle, please find the below output of the query and it is one day behind. The google is returning results only to change the format of the default systimestmap, but i need to change the value itself. Please suggest.
select systimestamp from dual
SYSTIMESTAMP
12-02-17 07:29:26.843712000 PM +05:30
Do you want to provide your own value and turn in into a timestamp like this?
SELECT TO_TIMESTAMP ('10-Sep-02 14:10:10.123000', 'DD-Mon-RR HH24:MI:SS.FF')
FROM DUAL;
Oracle documentation
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions193.htm
Related question:
Oracle: how to add minutes to a timestamp?
What about this?
SELECT SYSTIMESTAMP + INTERVAL '2' SECOND FROM dual;
With this method you are able to add or remove 'second's, 'minute's, 'hour's and so on...
Hope this helps :-)

My sysdate is not the same as the date showing in my desktop

I 've executed the following to know my sysdate and I discovered that the result is different from the date showing in my taskbar.
select to_char(sysdate,'DD-MON-YY HH:MI:SS') from dual;
How so ? and how to fix this
Please execute the below and post what you get:
select
to_char(sysdate,'mm/dd/rr hh24:mi:ss'),
to_char(current_date,'mm/dd/rr hh24:mi:ss'),
systimestamp,
sessiontimezone
from dual;
Per your comment, I see there is a difference in timezone configuration. So you would need to fix your DB's timezone to match with your OS' timezone.
The function sysdate is the date/time setting of the operating system where you run a certain db instance. But this is the date time (and timezone) when you start the instance and what was set in the shell or command prompt of the user (or a script) started the instance.
For example: if the timezone of a db server is set to CET and you logon this server and you open anyhow a shell with timezone configuration GMT and you (re-)start the instance in this shell then the timezone for sysdate will be GMT.
When possible re-start the instance from a shell/command prompt with that timezone configuration you like to have for your sysdate function.
BTW: systimestamp is the same as sysdate both including milliseconds but systimestamp includes also the timezone information for both sysdate and systimestamp. In addtion the function dbtimezone does not return the timezone which is used for sysdate. Only systimestamp can return the timezone of sysdate. dbtimezone is used for columns of datatype "timestamp with local timezone" nothing else.

Resources