Reputation: 2963
What is the best way/approach to store date/time info (and timestamps in general) so the information that can be displayed in different timezones?
My thoughts were to make the DB just hold time in a specified format (like GMT or UTC). When one reads from the DB, convert any date/time/timestamp data collected to the local timestamp for the area.
When inserting data into the DB. The following would apply.
- Collect the time from the User Interface as a string
- convert the time to the local date/time representation (where the timezone is included)
- convert the local date/time to GMT (or UTC)
- Save to the DB in GMT / UTC format
I have seen the Joda Time package and had considered using this as well.
What is the normal way that people go about resolving this issue? I hope this is not too vague - I have seen the Oracle DB here save date/time with a timezone that seems to be local.
Ex: I get the following:
SQL> SELECT EXTRACT(TIMEZONE_HOUR FROM SYSTIMESTAMP)||':'||
EXTRACT(TIMEZONE_MINUTE FROM SYSTIMESTAMP)
FROM dual;
Result => -5:0
Any hints on coming about this issue would be greatly appreciated.
TIA
Update
The following was done:
SQL> ALTER DATABASE SET TIME_ZONE = 'UTC';
The system was "bounced"
SQL> select dbtimezone from dual;
DBT
---
UTC
Out of curiosity, how are you doing your inserts into the DB tables so that the Timezone is taken into account? I get errors when using the TIMESTAMP type for a column:
SQL> create table shot (t timestamp);
Table created.
SQL> insert into shot values( '26-FEB-09 11.36.25.390713 AM Pacific/Auckland');
insert into shot values( '26-FEB-09 11.36.25.390713 AM Pacific/Auckland')
*
ERROR at line 1:
ORA-01830: date format picture ends before converting entire input string
SQL> insert into shot values( '26-FEB-09 11.36.25.390713 AM');
1 row created.
Update Also adding link to old post on setting the "session timezone" within java/jdbc/Oracle. If I am understanding this correctly, a certain .jar file is needed to be sure that the "session timezone" is the same as the "database timezone" when connecting to the database to run java code.
Setting session timezone with spring jdbc oracle
Upvotes: 4
Views: 3057
Reputation: 59486
I would recommend to use data type TIMESTAMP WITH LOCAL TIME ZONE
.
All values of TIMESTAMP WITH LOCAL TIME ZONE
are internally stored in DBTIMEZONE
, in your case UTC (thus you cannot change DBTIMEZONE
anymore once you have inserted any data of this data type). When you select such column then the time is always shown in current user session time zone, SESSIONTIMEZONE
. Hence it is essential to set your session time zone properly.
When you run insert into shot values( '26-FEB-09 11.36.25.390713 AM Pacific/Auckland');
you get an error because '26-FEB-09 11.36.25.390713 AM Pacific/Auckland'
is a string - not a timestamp!
You can insert timestamp values in various ways, for example:
TIMESTAMP '2009-02-16 23:36:25.390713 Pacific/Auckland'
TO_TIMESTAMP_TZ('26-FEB-09 11.36.25.390713 AM Pacific/Auckland', 'DD-MON-RR HH:MI:SS.FF AM TZR')
FROM_TZ(TIMESTAMP '2000-03-28 18:00:00', 'Pacific/Auckland')
FROM_TZ(TIMESTAMP '2000-03-28 18:00:00', SESSIONTIMEZONE)
(although you could skip it as SESSIONTIMEZONE
is the default)FROM_TZ(TO_TIMESTAMP('26-FEB-09 11.36.25.390713 AM', 'DD-MON-RR HH:MI:SS.FF AM'), 'Pacific/Auckland')
Be careful with these expressions:
TIMESTAMP '1999-10-29 01:30:00' AT TIME ZONE 'Pacific/Auckland'
TO_TIMESTAMP('26-FEB-09 11.36.25.390713 AM', 'DD-MON-RR HH:MI:SS.FF AM') AT TIME ZONE 'Pacific/Auckland'
TIMESTAMP '1999-10-29 01:30:00' AT TIME ZONE 'Pacific/Auckland'
actually means (FROM_TZ(TIMESTAMP '1999-10-29 01:30:00', 'SESSIONTIMEZONE') AT TIME ZONE 'Pacific/Auckland'
, so you may get an unwanted time shift.
Note, when you use TIMESTAMP
literal then the format is fix at YYYY-MM-DD HH24:MI:SS
If you don't specify any time zone information (for example TIMESTAMP '2009-02-16 11:36:25'
) then Oracle considers it as current user session time zone SESSIONTIMEZONE
.
SYSTIMESTAMP
returns current time in the time zone of database server's operating system, not at DBTIMEZONE
- although often they are set to the same value.
CURRENT_TIMESTAMP
returns current time in current user session time zone. Data type is TIMESTAMP WITH TIME ZONE
.
LOCALTIMESTAMP
also returns current time in current user session time zone, however data type is TIMESTAMP
, not TIMESTAMP WITH TIME ZONE
.
Another note, when you have TIMESTAMP WITH LOCAL TIME ZONE
then you cannot format output like this SELECT TO_CHAR(t, 'DD/MM/YYYY HH24:MI:SS ZTR') FROM shot
because by definition TIMESTAMP WITH LOCAL TIME ZONE
is always shown in current user session time zone and TZR
(i.e. Time zone region name) does not make any sense. Well, you could consider this as an Oracle bug, but to a certain extent it makes sense.
Upvotes: 4