In my previous article Oracle, SQL, Dates and Timestamps I talked about inserting, selecting and comparing dates in Oracle. Now I want to cover some functionality for converting between time zones.
We’ll use the table in the form specified in the previous article, but insert one more row:
insert into dates values(6, to_date('09/20/05 23:15', 'MM/DD/YY HH24:MI'));
The contents of the table now look like this:
1 09/14/05, 21:08
2 09/27/05, 00:00
3 10/02/05, 22:05
4 09/01/05, 17:01
5 09/12/05, 14:30
6 09/20/05, 23:15
Changing Time Zones
The date format in Oracle does not contain time zone information, but the database does. To find out the time zone set, execute this query:
SELECT dbtimezone FROM dual;
DBTIME
------
-04:00
The time zone can be updated with the command:
ALTER database SET TIME_ZONE = '-05:00';
where you can specify the offset from Greenwich mean time or a valid time zone from the list in the v$timezone_names
view. Note that this is one of the few of the ‘v$’ views which are plural.
Switching Time Zones
The function new_time
is used to convert a time to different time zones. To illustrate this we’ll look at entry 5 from the dates file.
SELECT entry, to_char(entry_date, 'MM/DD/YY HH:MI AM') FROM dates WHERE entry=5;
5 09/12/05 02:30 PM
This database is in US Eastern time but we want to display the time in US Central.
SELECT entry, to_char(new_time(entry_date, 'EST', 'CST'), 'MM/DD/YY HH:MI AM') FROM dates WHERE entry=5;
5 09/12/05 01:30 PM
Here we clearly see the time converted to Central. Note that the new_time
function is performed on the date field, not on the to_char
. Now let’s grab this time in Pacific time:
SELECT entry, to_char(new_time(entry_date, 'EST', 'PST'), 'MM/DD/YY HH:MI AM') FROM dates WHERE entry=5;
5 09/12/05 11:30 AM
Now we see not only the time converted, but also the time of day has gone from PM to AM.
Now let’s take a look at entry 6:
SELECT entry, to_char(entry_date, 'MM/DD/YY HH:MI AM') FROM dates WHERE entry=6;
6 09/20/05 11:15 PM
We’ll again assume this timestamp is in US Eastern time, but let’s convert it this time to Greenwich Mean Time.
SELECT entry, to_char(new_time(entry_date, 'EST', 'GMT'), 'MM/DD/YY HH:MI AM') FROM dates WHERE entry=6;
6 09/21/05 04:15 AM
This shows not only the change in hours, but that the date of this entry is displayed properly for its time zone.
Of course the new_time function can be used on inserts in the same way. This is useful if you are allowing input from people in different geographical regions. Here we convert an entry made in Pacific Time to Eastern:
INSERT INTO dates
VALUES (7,
new_time(to_date('09/22/05 10:28 AM', 'MM/DD/YY HH:MI AM'), 'PST', 'EST'));
SELECT entry, to_char(entry_date, 'MM/DD/YY HH:MI AM') FROM dates WHERE entry=7;
7 09/22/05 01:28 PM
So we have converted 10:28 AM Pacific to 1:28 PM Eastern so all our entries in the table are consistent. Of course when performing the insert we need to put the to_date
function within the new_time
function so the text string is converted to a date format before we try to convert it.
i got a small article about date functions difference and time zones: http://devtime.blogspot.com/2005/12/oracle-datetime-functions.html
hi, how would i be able display a date and time with time zone format. thanks.
e.g.
17-Mar-2006 14:30:00 EST
The query
SELECT entry, to_char(new_time(entry_date, ‘EST’, ‘GMT’), ‘MM/DD/YY HH:MI AM’) FROM dates WHERE entry=6;
in the example above returns correct GMT time only when daylight saving is not in effect. What do to do if daylight saving is in effect?
Any suggestions would be of great help.
Thanks,
Niks.
Niks, I think you would have to write a custom procedure for this which would use EST for Eastern and EDT for dayligt savings.
You would probably want to set up a table which would contain the begin and end dates for all the years you’re concerned with then use BETWEEN to check it. If it is BETWEEN the EDT start and end dates you would return EDT for the from time zone, if not you would return EST.
Sorry it’s not an easier answer, but as far as I can tell Oracle doesn’t provide an easy way to do this.
Jon
I need to convert from dbtimezone to sessiontimezone, however
NEW_TIME(date,dbtimezone,sessiontimezone) doesn’t work – does this function only work with timezone abreviations? Anyway to simply convert dbtimezone, sessiontimezone to the correct abbreviation?
Marty, I had troubles reproducing what you’re trying to do (there’s something funny with timezones in my databases… I’ll have to fix that later.)
I did turn up a couple articles elsewhere which may help you. Sounds like you’ll want to do something like
select
(substr(tz_offset(sessiontimezone),1,1)||1)*to_dsinterval(‘0 ‘ || substr(tz_offset(sessiontimezone), 2, 5) || ‘:00’) –
(substr(tz_offset(dbtimezone),1,1)||1)*to_dsinterval(‘0 ‘ || substr(tz_offset(dbtimezone), 2, 5) || ‘:00’)
from dual;
It’s a bit convoluted, but basically this gets the sessiontimezone into an acceptable date interval and subtracts the dbtimezone. The result is a date interval which you would add to a date in the session timezone to convert it to the system timezone.
Here are two other articles I turned up on the topic which may help:
From AskTom
From dbasupport.com
Hope this helps. This really does emphasize how painful it is to deal with Oracle dates.
Hi,
The article presented is really very good. I do not know the time zone corresponding to CET. My query
select to_char(new_time(sysdate, ‘CET’, ‘GMT’)) from dual
throws me error that the time zone is not valid.
Request you kindly let me know the valid time zone.
Thanks and Regards,
Vasant
vasantmv@gmail.com
Vasant,
It turns out new_time will only accept a handful of US timezones. It’s probably possible to do some tricks with the
tz_offset
and thenumtodsinterval
functions but the easiest thing to do in most cases is to just add/subtract the appropriate number of hours for your timezone.For example, in Eastern/US I would add 5 hours to find out the GMT value like this:
select sysdate + 5/24 from dual;
Hope this helps.
Jon
Useful article, thanks. Note that a database restart is required in order for the alter database set TIME_ZONE= to take effect.
Sergio
I have a database that stores date values in GMT, and currently the DBTIMEZONE is set to GMT as well, if I change the DBTIMEZONE, will dates be displayed in the GMT (stored) format, or will they be displayed in the DBTIMEZONE offset from GMT?
Thansk!
Jeff
Jeff,
You should check the docs for your version of Oracle. I believe this varies, but my guess is your dates will continue to be displayed in their originally inserted GMT.
Vasant,
There is another way you can check..
You need to alter your session.. Here is an example to convert from CET to EST..
alter session set nls_date_format = ‘DD.MM.YYYY HH24:MI:SS’;
alter session set NLS_TIMESTAMP_FORMAT = ‘DD.MM.YYYY HH24:MI:SSXFF’;
alter session set time_zone = ‘US/Eastern’;
select id,time1, to_date(to_char((from_tz(to_timestamp(time1, ‘dd-mm-yyyy hh24:mi:ss’) ,’Europe/BRUSSELS’)
at time zone ‘US/Eastern’),’mm-dd-yyyy hh24:mi:ss’),’mm-dd-yyyy hh24:mi:ss’) from Table1
This will also takes care of Daylight Savings.
Hope this helps.
Prasad.
very useful and well presented information. Thank you
I’ve got a problem with java that extends to dbtimezone. If the dbtimezone defaults to a given timezone (ostensibly when created if not explicitly stated it’s SUPPOSED to get the OS timezone and I can’t see that ANYWHERE in the registry of my windows machine where it’s set to GMT -7:00 (we’re in GMT -6:00)) when it’s created, and its default in this case is off by an hour compared to the server it’s on, the java I’m calling converts the milliseconds of a given date according to the offset between the dbtimezone and the server setting)… When I change the dbtimezone to match the server and restart the instance it STILL acts as if it’s in the old time zone.
we have used this two function:
(each schema has its own time_zone stored in sys_values table)
create or replace
function LOC_DATETIME(pDATE in date) return date is
vTimeZone varchar2(50);
vDbZone varchar2(50);
begin
select TIME_ZONE into vTimeZone from sys_values;
vDbZone := ‘Europe/BRUSSELS’;
return
to_date(to_char(from_tz(TO_TIMESTAMP(to_char(pDATE,’mm-dd-yyyy hh24:mi:ss’),
‘mm-dd-yyyy hh24:mi:ss’),vDbZone) at time zone vTimeZone,’mm-dd-yyyy hh24:mi:ss’), ‘mm-dd-yyyy hh24:mi:ss’);
end;
/
create or replace
function DB_DATETIME(pDATE in date) return date is
vTimeZone varchar2(50);
vDbZone varchar2(50);
begin
select TIME_ZONE into vTimeZone from sys_values;
vDbZone := ‘Europe/BRUSSELS’;
return
to_date(to_char(from_tz(TO_TIMESTAMP(to_char(pDATE,’mm-dd-yyyy hh24:mi:ss’),
‘mm-dd-yyyy hh24:mi:ss’),vTimeZone) at time zone vDbZone,’mm-dd-yyyy hh24:mi:ss’), ‘mm-dd-yyyy hh24:mi:ss’);
end;
/
it works
Found answer to my question/issue quickly (wanted to see some columns in different timezones). Thanks
Thanks for the information.But I have a query.
How we can convert GMT to GMT+4.
Hi All,
I am a newbie in this domain. And would like to know how I can convert GMT into other TimeZones?
I have a timestamp in GMT and want to convert it to EST and MST, how I can use oracle to convert this?
Will Appreciate your response.
Thanks,
Sunil