Oracle 10g Time Zone Confusion - oracle

SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI')
,TO_CHAR(CURRENT_DATE, 'YYYY-MM-DD HH24:MI')
,TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI TZR')
,TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MI TZR')
,TO_CHAR(LOCALTIMESTAMP, 'YYYY-MM-DD HH24:MI TZR')
,DBTIMEZONE
,SESSIONTIMEZONE
FROM DUAL;
Is returning:
2012-01-16 11:42
2012-01-16 11:42
2012-01-16 11:42 -06:00
2012-01-16 11:42 -06:00
2012-01-16 11:42 +00:00
+00:00
-06:00
It seems to think the database time zone is GMT, yet the SYSDATE is the same as the CURRENT_DATE.
When I remote into that server (Windows), the time zone is apparently CST (however, I am aware that this could be picking up my Terminal Services Client Time Zone Offset, but this machine doesn't have Terminal Services on it, just administrative)
Running the same thing against a server in Amsterdam (4 minutes later all from the same TOAD client), I'm getting:
2012-01-16 18:46
2012-01-16 11:46
2012-01-16 18:46 +01:00
2012-01-16 11:46 -06:00
2012-01-16 11:46 +00:00
+02:00
-06:00
Note the +2, but at least the SYSDATE and CURRENT_DATE are differing.
What is going on here? Where does SYSDATE come from and is there anything else which affects it?
It seems like DBTIMEZONE is not used for any of these things? So what is DBTIMEZONE used for?

There are actually 3 timezones here, not 2
the timezone of the session/client
Shown in SESSIONTIMEZONE
This is the timezone of CURRENT_DATE, LOCALTIMESTAMP and CURRENT_TIMESTAMP. The difference between those 3 is the return type, they return a DATE, TIMESTAMP, and TIMESTAMP WITH TIME ZONE respectively)
The database timezone
Shown in DBTIMEZONE
This is the the timezone used for the internal storage of TIMESTAMP WITH LOCAL TIME ZONE values. Note that values are converted to/from session timezone on insert/select so it actually isn't as important as it seems
This is NOT the timezone of SYSDATE/SYSTIMESTAMP
The database OS timezone
In unix, it is based on the TZ variable when Oracle is started
This is the timezone of SYSDATE and SYSTIMESTAMP
In your first example, I can see that the session TZ is UTC-6, the database TZ is UTC, and the database OS timezone is UTC-6.
In your second example, I can see that the session TZ is UTC-6, the database TZ is UTC+2, and the database OS timezone is UTC+1.

The details are in the fine print of the documentation. Take a look at the Return Type, and the actual Timezone the DATE or TIMESTAMP is calculated in.
SYSDATE
Return Type: DATE
Time Zone: Host OS of Database Server
CURRENT_DATE
Return Type: DATE
Time Zone: Session
SYSTIMESTAMP
Return Type: TIMESTAMP WITH TIME ZONE
Time Zone: Host OS of Database Server
CURRENT_SYSTIMESTAMP
Return Type: TIMESTAMP WITH TIME ZONE
Time Zone: Session
LOCALTIMESTAMP
Return Type: TIMESTAMP
Time Zone: Session
DBTIMEZONE
Time Zone: DB Time Zone. Inherits from DB Server OS, but can be overridden using set at DB Creation or Alter using TIME_ZONE DB Parameter (SET TIME_ZONE=...). This affects the time zone used for TIMESTAMP WITH LOCAL TIME ZONE datataypes.
SESSIONTIMEZONE
Time Zone: Session Timezone. Inherits from Session hosting OS, but can be overridden using ALTER SESSION (ALTER SESSION SET TIME_ZONE=...).
Return Type, indicates whether or not the Timezone is available within the Datatype. If you try to print TZR if datatype does not carry TimeZone, then it will just show up as +00:00 (doesn't mean it is GMT). Otherwise It will show the TimeZone matching either the Database or Session as indicated.
Time Zone, indicates in which Timezone the time is calculated. For matching TimeZone, the same Date/Time will be shown (HH24:MI).
Note that none of the FUNCTIONS return TIME in the Time Zone set with the DB TIME_ZONE (or as returned by the DBTIMEZONE function). That is, none of the functions also return a datatype of TIMESTAMP WITH LOCAL TIME ZONE. Howver you can convert the output of any of the functions that does return a timezone into a different timezone (including DBTIMEZONE) as follows:
SELECT SYSTIMESTAMP AT TIME ZONE DBTIMEZONE FROM DUAL;
More information on my blog.

Use UTC time and offset your timezone from UTC, To get UTC in Oracle use SYS_EXTRACT_UTC
Convert SYSTEMDATE to UTC
select sys_extract_utc(systimestamp) from dual;
As for the difference the definition from Oracle documentation might help to explain:
LOCALTIMESTAMP returns the current date and time in the session time zone in a value of datatype TIMESTAMP
CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE
SYSTIMESTAMP returns the system date, including fractional seconds and time zone, of the system on which the database resides
CURRENT_DATE returns the current date in the session time zone, in a value in the Gregorian calendar of datatype DATE.
SYSDATE returns the current date and time set for the operating system on which the database resides.
DBTIMEZONE returns the value of the database time zone.

Related

Different time sysdate and current_date when connect to database since application server

I have a problem with the time that Oracle gives me when working with applications.
I currently connect from an application server (apx1) to a server containing Oracle 19c (bdx1) for database operations.
Both the application server and the database server are in the Canary Islands, so it must show/work local time there (GMT +1 in summer, GMT in winter).
If I launch the date command on the servers, the time appears correct.
[oracle#apx1 oracle]$ date
vie jul 1 14:25:49 BST 2022
[oracle#bdx1 ~]$ date
vie jul 1 14:25:46 BST 2022
However, after making the connection from apx1 to bdx1, I get this time offset:
SQL> select systimestamp, current_timestamp, localtimestamp from dual;
SYSTIMESTAMP
---------------------------------------------------------------------------
CURRENT_TIMESTAMP
---------------------------------------------------------------------------
LOCALTIMESTAMP
---------------------------------------------------------------------------
01/07/22 15:27:39,762772 +02:00
01/07/22 14:27:39,762775 +01:00
01/07/22 14:27:39,762775
The SESSIONTIMEZONE parameter returns the correct value, +1:
SQL> SELECT SESSIONTIMEZONE FROM DUAL;
SESSIONTIMEZONE
---------------------------------------------------------------------------
+01:00
However, if I run this query (from the application server to the database):
sac#apx1> sqlplus user/pass#bdx1
SQL> select to_char(sysdate, 'dd mm yyyy hh24:mi:ss') "SYSDATE", to_char(current_date, 'dd mm yyyy hh24:mi:ss') "CURRENT_DATE" from dual;
SYSDATE CURRENT_DATE
------------------- -------------------
01 07 2022 16:26:23 01 07 2022 15:26:23
SYSDATE result is incorrect with respect to the time that should appear.
What do you mean by "configure to correct this offset"?
LOCALTIMESTAMP returns the current date and time in the session time zone in a value of datatype TIMESTAMP.
CURRENT_TIMESTAMP returns the current date and time in the session time zone in a value of datatype TIMESTAMP WITH TIME ZONE.
SYSTIMESTAMP returns the current date and time in the time zone of database server's operating system in a value of datatype TIMESTAMP WITH TIME ZONE.
Set the SESSIONTIMEZONE and/or database server time zone properly.
The solution was posted on DBA stackexchange: https://dba.stackexchange.com/a/314026/175060.
You have to set the parameter at cluster level:
srvctl setenv database -db DBNAME -env "TZ=Atlantic/Canary".
And then restart the DB hosts, since a CRS restart is not enough.

Oracle current_timestamp method stores timestamp column values with GMT timezone instead of local timezone

Column is defined as of type Timestamp:
CREATE_TS NOT NULL TIMESTAMP(6)
While doing an insert we use Oracle CURRENT_TIMESTAMP method to store the timestamp data.
The database is set with EST/EDT timezone:
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;
SESSIONTIMEZONE
CURRENT_TIMESTAMP
America/New_York
08-JUN-22 12.40.26.305481000 AM AMERICA/NEW_YORK
Data stored with GMT timezone, can someone please provide if there is any explanation/suggestions this is causing?|
CURRENT_TIMESTAMP returns the timestamp based on the time zone of the client.
SYSTIMESTAMP returns the timestamp based on the time zone of the server's operating system.
If you INSERT data from a client application that is configured to be in the GMT time zone then when you use CURRENT_TIMESTAMP you will get a GMT time zone.
If you want to use the server's time zone and not the client's then use SYSTIMESTAMP.

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

Trying to retrieve the UTC time-stamp in Oracle, does using "from_tz" cause an issue?

Will using the following query to retrieve the UTC timestamp from an oracle database cause an issue? I do not want to alter the database timezone parameter in order to retrieve the correct date. I do not want to do alter database set time_zone.
My query at the moment is:
select from_tz(CAST (sys_extract_utc(systimestamp) AS TIMESTAMP), '+00:00') from dual;
I would like to know if this query will result in the correct UTC date in all circumstances regardless of the EST/EDT status.
I don't see anything wrong with your query. Note that if you want to work in UTC for your session, you could simply:
ALTER SESSION SET TIME_ZONE = '0:00';
select CURRENT_TIMESTAMP from dual;
output
11/1/2016 5:48:55.115282 PM +00:00
That would change your current_timestamp (and localtimestamp) for your entire session.
Your query is just setting timezone but not converting time. If that's what you were looking for it is ok. Is local time is 3AM you will return 3AM UTC.
I think you're looking for that query:
select cast(sysdate as timestamp) at time zone 'UTC' from dual;
And the apply
select from_tz(cast(systimestamp at time zone 'UTC' as timestamp), '+0:00') from dual;
Some general notes:
SYSTIMESTAMP and SYSDATE are given in time zone of your database server's operating system. Thus changing database time zone (i.e. DBTIMEZONE) does not change anything.
CAST (sys_extract_utc(systimestamp) AS TIMESTAMP), resp. cast(systimestamp at time zone 'UTC' as timestamp) have a problem. You convert your timestamp to UTC but by CAST(... AS TIMESTAMP) you remove any time zone information from that value. If you like to do any further conversion (e.g. again to TIMESTAMP WITH TIME ZONE value) then your input UTC value is considered to be a SESSIONTIMEZONE value.
from_tz(CAST (sys_extract_utc(systimestamp) AS TIMESTAMP), '+00:00') does following:
Get current time in time zone of your database server's operating system, include time zone information.
Convert this time to UTC, cut time zone information
Append time zone information (+00:00) to this value
Correct output but redundant conversion
cast(sysdate as timestamp) at time zone 'UTC' does following:
Get current time in time zone of your database server's operating system, without any time zone information.
Cast to TIMESTAMP (basically no effect at all)
Consider this value as time in your local session time zone (SESSIONTIMEZONE) and convert to UTC.
Correct output only if time zone of your database server's operating system is the same as your local session time zone, otherwise you get wrong result.
from_tz(cast(systimestamp at time zone 'UTC' as timestamp), '+0:00') does following:
Get current time in time zone of your database server's operating system, include time zone information.
Convert this time to UTC
Cut time zone information
Append time zone information (+00:00) to this value
Correct output but redundant conversion
from_tz(cast(systimestamp as timestamp), '+0:00') does following:
Get current time in time zone of your database server's operating system, include time zone information.
Cut time zone information
Append time zone information (+00:00) to this value
Correct output only if time zone of your database server's operating system is UTC.

Issue with timezone in oracle

Below query is used in my code to get the timezone from database. (DB is in central time zone)
SELECT DBTIMEZONE FROM DUAL;
-05:00
When daylight saving is on (CDT), its expected result.
but when daylight saving ends (CST), my result should be GMT-06, but i am still getting GMT-05.
Googled and got below options :
SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual;
SELECT TZ_OFFSET('CST6CDT') FROM DUAL;
Will above queries run correctly accordingly to CST and CDT ??
DBTIMEZONE does not determine the time zone of SYSTIMESTAMP (or SYSDATE)
Time zone of SYSTIMESTAMP is the time zone of database server's operating system.
DBTIMEZONE is only relevant for data type TIMESTAMP WITH LOCAL TIME ZONE and defines the time zone in which those values are stored internaly. You cannot change DBTIMEZONE on your database if the database contains a table with a TIMESTAMP WITH LOCAL TIME ZONE column and the column contains data.

Resources