Just when you thought you knew where you were, Oracle has implemented time zones to totally zone us out. Come along and let’s figure where we are on this great planet.
A few articles back I wrote on a comparison between the DATE datatype and the TIMESTAMP datatype. This article goes one step further and explores Oracle’s TIME ZONE feature of the TIMESTAMP datatype. In particular, Oracle has added the “WITH TIME ZONE” and the “WITH LOCAL TIME ZONE” to the TIMESTAMP datatype.
Valid Time Zones
You have two options when setting which time zone the database belongs to. You can either qualify it as a displacement from GMT/UTC in the format of ‘hh:mm’ or you can specify it as a name that has an entry in the V$TIMEZONE table. Listing 1 shows the SQL I used to display the valid time zone name in the Mountain Standard Time Zone.
Listing 1
Show valid time zone names for MST
SQL> select tzname,tzabbrev from V$TIMEZONE_NAMES where tzabbrev = 'MST' TZNAME TZABBREV ------------------------- ---------- America/Denver MST America/Edmonton MST America/Ensenada MST America/Mazatlan MST America/Mexico_City MST America/Phoenix MST America/Regina MST America/Shiprock MST America/Tijuana MST Canada/East-Saskatchewan MST Canada/Mountain MST Canada/Saskatchewan MST Europe/Moscow MST Mexico/BajaNorte MST Mexico/BajaSur MST Mexico/General MST MST MST MST7MDT MST Navajo MST US/Arizona MST US/Mountain MST W-SU MST
DBTIMEZONE
At the core of time zones is the database time zone. You can look at the time zone that was selected at database creation by issuing the SQL in Listing 2. If you want to change the DBTIMEZONE you will need to issue an ALTER DATBASE command such as in Listing 3. In order for the new DBTIMEZONE to take effect, you must bounce the database. In addition, if you have any data type columns that are of the TIMESTAMP with TIME ZONE defined, you will not be able to reset the DBTIMEZONE. After bouncing the database, you can issue the SQL in Listing 4 to validate that the change has taken place. If you wanted to switch back to the “hh:mm” format for DBTIMEZONE, just issue the SQL in Listing 5.
Listing 2
Check the database time zone
SQL> select DBTIMEZONE from dual; DBTIME ------ -07:00
Listing 3
Changing the database time zone
SQL> ALTER database SET TIME_ZONE = 'America/Denver'; Database altered.
Listing 4
Validate the change in DBTIMEZONE
SQL> select DBTIMEZONE from dual; DBTIMEZONE --------------- America/Denver
Listing 5
Switch back DBTIMEZONE to hh:mm format
SQL> ALTER database SET TIME_ZONE = '-07:00';
SESSIONTIMEZONE
If you do not want to use the database time zone, Oracle gives you the option to set the time zone at the session level. Issue the SQL in Listing 6 if you want a different time zone for the current session to which you are connected. You can check the session time zone by issuing the SQL in Listing 7.
Listing 6
Set time zone at the session level
SQL> alter session set TIME_ZONE='-03:00'; Session altered.
Listing 7
Check session level time zone
SQL> select SESSIONTIMEZONE from dual; SESSIONTIMEZONE ------------------------------------------------- -03:00
SYSTIMESTAMP
Just as there is a call to SYSDATE to get the current system date and time, there is a call to get the current system date, time and time zone. The data type returned is of TIMESTAMP WITH TIME ZONE. Issue the SQL in Listing 8 to get the current system time information.
Listing 8
Get current system timestamp with time zone information
SQL> select SYSTIMESTAMP from dual; SYSTIMESTAMP ----------------------------------------------- 01-SEP-03 10.53.13.574000 AM -07:00
CURRENT_TIMESTAMP
The counter part of the SYSTIMESTAMP function for session current date and time is the CURRENT_TIMESTAMP function call. This will return what the current time stamp of the session is in relation to the session time zone (SESSIONTIMEZONE). Therefore, if we have the session time zone as defined in Listing 6, we can check the timestamp of the session by issuing the SQL in Listing 9.
Listing 9
Local timestamp for session
SQL> select CURRENT_TIMESTAMP from dual; CURRENT_TIMESTAMP ------------------------------------------------- 01-SEP-03 02.53.33.753000 PM 03:00
TIMESTAMP datatype with TIME ZONE Information
At the heart of storing time zone information within a table, Oracle has defined the TIMESTAMP data type. This is Oracle’s great new hope for giving the old DATE datatype a more granular mechanism of holding not only date and time information but also fractional seconds. Look at A Comparison of Oracle’s DATE and TIMESTAMP Datatypes for a discussion of this databtype. For the remainder of this article and for the purposes of exploiting the time zone options for the TIMESTAMP datatype, I have created a table as defined in Table 1. In Listing 10, I have created a quick example of how the TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE datatypes will behave when used to store information. To begin with I have set the DBTIMEZONE and SESSION TIMEZONE to be the same value ‘-07:00’. I then insert into the DATE_TABLE the value of a system time stamp. I then change the time zone for the current session only to be ‘-03:00’. This will set the current session four hours ahead of the database time zone. I then insert into the DATE_TABLE a row that will hold the current session timestamp. The main idea to grasp here is that the column with datatype TIMESTAMP WITH TIME ZONE stores and displays the explicit time supplied from the INSERT statement. The column with datatype TIMESTAMP WITH LOCAL TIME ZONE stores the explicit time supplied but will display a value that is relative to the current session time zone. This means that if you want hard and fast TIMESTAMPS with time zone information stored, you should use the TIMESTAMP WITH TIME ZONE datatype. If you are concerned more with giving date and time information to customers in different time zones and represented in their local time, you should use the TIMESTAMP WITH LOCAL TIME ZONE datatype.
Table 1:
Create table with different TIMESTAMP columns
create table date_table ( time_stamp_tz TIMESTAMP WITH TIME ZONE, time_stamp_ltz TIMESTAMP WITH LOCAL TIME ZONE);
LISTING 10
Inserting SYSTIMESTAMP into DATE_TABLE
SQL> select dbtimezone,sessiontimezone from dual; DBTIMEZONE SESSIONTIMEZONE ---------- ---------------- -07:00 -07:00 SQL> insert into date_table values (SYSTIMESTAMP,SYSTIMESTAMP); 1 row created. SQL> alter session set time_zone='-03:00'; Session altered. SQL> select dbtimezone,sessiontimezone from dual; DBTIMEZONE SESSIONTIMEZONE ---------- ---------------- -07:00 -03:00 SQL> insert into date_table values (LOCALTIMESTAMP,LOCALTIMESTAMP ); 1 row created. SQL> select time_stamp_tz, time_stamp_ltz from date_table; TIME_STAMP_TZ TIME_STAMP_LTZ ------------------------------------- ------------------------------ 01-SEP-03 10.57.36.642000 AM -07:00 01-SEP-03 02.57.36.642000 PM 01-SEP-03 02.57.48.549000 PM -03:00 01-SEP-03 02.57.48.549000 PM SQL> alter session set time_zone='-07:00'; Session altered. SQL> select time_stamp_tz, time_stamp_ltz from date_table; TIME_STAMP_TZ TIME_STAMP_LTZ ------------------------------------- ------------------------------ 01-SEP-03 10.57.36.642000 AM -07:00 01-SEP-03 10.57.36.642000 AM 01-SEP-03 02.57.48.549000 PM -03:00 01-SEP-03 10.57.48.549000 AM
We have all grown up and accepted time zones. It has always been easy to do the hour difference in our heads when calling someone or traveling to a different time zone. For some reason the implementation of time zones through offsets of the GMT/UTC made it difficult for me to conceptualize and figure out where and what time it truly is. I would suggest that you play around with the example that I have given you so that you may become acquainted with this feature and where on earth you are.