What is the best way to always get the right time in Europe/Paris (including summer/winter times) ?
So far, I'm using the following query :
select FROM_TZ(CAST(Sysdate AS TIMESTAMP), 'Europe/Paris') from dual
It was working nicely in a previous server. However, we have changed our database server and now we are getting a difference of one hour.
Is there any way to get always the correct time in Paris ?
Thanks.
SYSDATE is returned in the time zone of database server's operating system. When you run FROM_TZ(CAST(Sysdate AS TIMESTAMP), 'Europe/Paris') then you "attach" time zone Europe/Paris to SYSDATE.
So, FROM_TZ(CAST(Sysdate AS TIMESTAMP), 'Europe/Paris') is only correct if the time zone of database server's operating system is Europe/Paris.
Try SYSTIMESTAMP AT TIME ZONE 'Europe/Paris' then result is always correct because SYSTIMESTAMP returns a TIMESTAMP WITH TIME ZONE value and time zones are properly converted.
Related
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
In one of the Oracle database server it is showing "+01:00" when I fire the "Select dbtimezone from dual" does that mean in summer the clock will shift one hour ahead ?. In another server it is showing "+00:00" does that mean the database server setting is GMT ? but I am using the sysdate in oracle pl/sql. Client is saying the Aix server is on DST so would that mean the DB server will adopt the AIX server setting after clock change ?
How to fix this problem.
Answer is: It depends.
In total your database has three time zones
1. Your session time zone: SESSIONTIMEZONE
This you can change by ALTER SESSION SET TIME_ZONE=... at any time. It is relevant for result of
CURRENT_DATE
LOCALTIMESTAMP
CURRENT_TIMESTAMP
It is also the target time zone when you do CAST({TIMESTAMP/DATE without any timezone} AS TIMESTAMP WITH {LOCAL} TIME ZONE)
Default SESSIONTIMEZONE can be set by environment variable ORA_SDTZ or (on Windows) by registry entry HKLM\SOFTWARE\Wow6432Node\ORACLE\KEY_%ORACLE_HOME_NAME%\ORA_SDTZ (for 32 bit Client), resp. HKLM\SOFTWARE\ORACLE\KEY_%ORACLE_HOME_NAME%\ORA_SDTZ (for 64 bit Client).
2. The database time zone: DBTIMEZONE
Actually this is not so important in daily use, it is relevant only for TIMESTAMP WITH LOCAL TIME ZONE data type columns and defines the storage format.
This is NOT the timezone of SYSDATE or SYSTIMESTAMP!!!
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. Otherwise it can be changed with ALTER DATABASE SET TIME_ZONE='...';. The change does not take effect until the database has been shut down and restarted.
DBTIMEZONE is set when database is created. If no time zone is provided while database creation then Oracle defaults to the time zone of the server's operating system.
3. The time zone of database server's operating system:
This time zone is relevant for result of
SYSDATE
SYSTIMESTAMP
Naturally this time zone cannot be changed on database level. In case your home country uses Daylight Saving Times, this time zone may change twice a year. You can interrogate it with SELECT TO_CHAR(SYSTIMESTAMP, 'tzr') FROM dual;, for instance.
So, if your DB Server OS is setup properly, then you should get summer times from next week on (at least for Europe)
In one of the Oracle database server it is showing "+01:00" when I fire the "Select dbtimezone from dual" does that mean in summer the clock will shift one hour ahead ?
It means your database timezone is +01:00 compared to UTC time zone.
From docs,
DBTIMEZONE returns the value of the database time zone. The return
type is a time zone offset (a character type in the format
'[+|-]TZH:TZM') or a time zone region name, depending on how the user
specified the database time zone value in the most recent CREATE
DATABASE or ALTER DATABASE statement.
So, database's DBTIMEZONE inherits the timezone value from DB Server OS.
While SESSIONTIMEZONE could be overridden at session level by an alter session statement.
For example,
ALTER SESSION SET TIME_ZONE=<timezone>;
This modifies the time zone of the TIMESTAMP WITH LOCAL TIME ZONE.
In another server it is showing "+00:00" does that mean the database server setting is GMT ?
+00:00 can be assumed that the database time zone is set to UTC time zone.
For example,
SELECT DBTIMEZONE FROM DUAL;
DBTIME
------
+00:00
Read more from documentation.
I resolved this issue by using the below command
"Select Systimestamp at time zone 'GMT' from DUAL' This command wil always give the GMT date and time irrespective of OS time.
Oracle Database automatically determines whether Daylight Saving Time is in effect for a specified time zone and returns the corresponding local time. Normally, date/time values are sufficient to allow Oracle Database to determine whether Daylight Saving Time is in effect for a specified time zone. The periods when Daylight Saving Time begins or ends are boundary cases. For example, in the Eastern region of the United States, the time changes from 01:59:59 a.m. to 3:00:00 a.m. when Daylight Saving Time goes into effect. The interval between 02:00:00 and 02:59:59 a.m. does not exist. Values in that interval are invalid. When Daylight Saving Time ends, the time changes from 02:00:00 a.m. to 01:00:01 a.m.
Further explaination can be found here.
http://docs.oracle.com/cd/E18283_01/server.112/e10729/ch4datetime.htm#insertedID11
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.
In one of the Oracle database server it is showing "+01:00" when I fire the "Select dbtimezone from dual" does that mean in summer the clock will shift one hour ahead ?. In another server it is showing "+00:00" does that mean the database server setting is GMT ? but I am using the sysdate in oracle pl/sql. Client is saying the Aix server is on DST so would that mean the DB server will adopt the AIX server setting after clock change ?
How to fix this problem.
Answer is: It depends.
In total your database has three time zones
1. Your session time zone: SESSIONTIMEZONE
This you can change by ALTER SESSION SET TIME_ZONE=... at any time. It is relevant for result of
CURRENT_DATE
LOCALTIMESTAMP
CURRENT_TIMESTAMP
It is also the target time zone when you do CAST({TIMESTAMP/DATE without any timezone} AS TIMESTAMP WITH {LOCAL} TIME ZONE)
Default SESSIONTIMEZONE can be set by environment variable ORA_SDTZ or (on Windows) by registry entry HKLM\SOFTWARE\Wow6432Node\ORACLE\KEY_%ORACLE_HOME_NAME%\ORA_SDTZ (for 32 bit Client), resp. HKLM\SOFTWARE\ORACLE\KEY_%ORACLE_HOME_NAME%\ORA_SDTZ (for 64 bit Client).
2. The database time zone: DBTIMEZONE
Actually this is not so important in daily use, it is relevant only for TIMESTAMP WITH LOCAL TIME ZONE data type columns and defines the storage format.
This is NOT the timezone of SYSDATE or SYSTIMESTAMP!!!
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. Otherwise it can be changed with ALTER DATABASE SET TIME_ZONE='...';. The change does not take effect until the database has been shut down and restarted.
DBTIMEZONE is set when database is created. If no time zone is provided while database creation then Oracle defaults to the time zone of the server's operating system.
3. The time zone of database server's operating system:
This time zone is relevant for result of
SYSDATE
SYSTIMESTAMP
Naturally this time zone cannot be changed on database level. In case your home country uses Daylight Saving Times, this time zone may change twice a year. You can interrogate it with SELECT TO_CHAR(SYSTIMESTAMP, 'tzr') FROM dual;, for instance.
So, if your DB Server OS is setup properly, then you should get summer times from next week on (at least for Europe)
In one of the Oracle database server it is showing "+01:00" when I fire the "Select dbtimezone from dual" does that mean in summer the clock will shift one hour ahead ?
It means your database timezone is +01:00 compared to UTC time zone.
From docs,
DBTIMEZONE returns the value of the database time zone. The return
type is a time zone offset (a character type in the format
'[+|-]TZH:TZM') or a time zone region name, depending on how the user
specified the database time zone value in the most recent CREATE
DATABASE or ALTER DATABASE statement.
So, database's DBTIMEZONE inherits the timezone value from DB Server OS.
While SESSIONTIMEZONE could be overridden at session level by an alter session statement.
For example,
ALTER SESSION SET TIME_ZONE=<timezone>;
This modifies the time zone of the TIMESTAMP WITH LOCAL TIME ZONE.
In another server it is showing "+00:00" does that mean the database server setting is GMT ?
+00:00 can be assumed that the database time zone is set to UTC time zone.
For example,
SELECT DBTIMEZONE FROM DUAL;
DBTIME
------
+00:00
Read more from documentation.
I resolved this issue by using the below command
"Select Systimestamp at time zone 'GMT' from DUAL' This command wil always give the GMT date and time irrespective of OS time.
Oracle Database automatically determines whether Daylight Saving Time is in effect for a specified time zone and returns the corresponding local time. Normally, date/time values are sufficient to allow Oracle Database to determine whether Daylight Saving Time is in effect for a specified time zone. The periods when Daylight Saving Time begins or ends are boundary cases. For example, in the Eastern region of the United States, the time changes from 01:59:59 a.m. to 3:00:00 a.m. when Daylight Saving Time goes into effect. The interval between 02:00:00 and 02:59:59 a.m. does not exist. Values in that interval are invalid. When Daylight Saving Time ends, the time changes from 02:00:00 a.m. to 01:00:01 a.m.
Further explaination can be found here.
http://docs.oracle.com/cd/E18283_01/server.112/e10729/ch4datetime.htm#insertedID11
Is there any way to get the current time for particular given time zone?
For EX: GetDateTime("Morocco Standard Time")
It should give the local time of time zone "Morocco Standard Time"
Thanks in Advance,
Merlin
I know that the question is quite old, but maybe the answer will help someone.
If you are using SQL Server 2016 you can use new feature AT TIME ZONE. Let's get to the result that you need step by step.
First, use function SYSDATETIMEOFFSET() to retrieve current date and time in UTC time zone. The return type of this function is DATETIMEOFFSET, which stores not only date, but also related time zone information:
SELECT SYSDATETIMEOFFSET()
-- Result is 2016-08-20 13:15:25.3760873 +03:00
Then this with AT TIME ZONE statement. This returns DATETIMEOFFSET in the time zone that you need:
SELECT SYSDATETIMEOFFSET() AT TIME ZONE 'Morocco Standard Time'
-- Result is 2016-08-20 11:15:25.3760873 +01:00
Additionally if you want to lose time zone information and use DATETIME, you can cast the above result to DATETIME:
SELECT CAST( SYSDATETIMEOFFSET() AT TIME ZONE 'Morocco Standard Time' AS DATETIME)
-- Result is 2016-08-20 11:15:25.376