Depending on the type, there are a couple of gotchas with regard to what time zone Oracle is converting from depending on what the data type of myTimestamp
is.
timestamp with time zone
It Just Works™. a_horse_with_no_name has the right answer here.
timestamp with local time zone
it is implicitly cast to timestamp with time zone, then It Just Works™. Again, a_horse_with_no_name is right here.
timestamp
While it too is implicitly cast to timestamp with time zone, the time zone that gets assigned by default is the session time zone (as opposed to the database time zone).
- The explicit invocation of this is
myTimestamp at local
.
- Alternatively (and most likely better), you can do as Madhawas says and use the
from_tz
function to explicitly build a value with an explicit time zone other than that of your session.
date
Trying to do any of the above to date will fail as you described:
myTimestamp at time zone 'UTC'
ORA-30084: invalid data type for datetime primary with time zone modifier
from_tz(myTimestamp, 'America/New_York')
ORA-00932: inconsistent datatypes: expected TIMESTAMP got DATE
The solution here is to cast the date to a timestamp first:
select from_tz(cast(myTimestamp as timestamp), 'America/New_York') from tableA
Sample Script
The following script illustrates the behavior. Note that on my system, dbtimezone
is US/Central, and sessiontimezone
is GMT-05:00.
I also use to_char
to convert the output as I have found some tools will alter the result timestamp in subtle ways, particularly if they don't have good timestamp support (this is rare nowadays, but still potentially a problem).
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'
/
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'
/
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZR'
/
select dbtimezone
,sessiontimezone
,to_char(timestamp '2017-01-01 06:00:00') as ts
,to_char(timestamp '2017-01-01 06:00:00' at local) as ts_at_local
,to_char(timestamp '2017-01-01 06:00:00' at time zone dbtimezone) as ts_at_db
,to_char(timestamp '2017-01-01 06:00:00' at time zone sessiontimezone) as ts_at_session
from dual
/
The output on my system is as follows (reformatted as columnar for readability):
DBTIMEZONE US/Central
SESSIONTIMEZONE -05:00
TS 2017-01-01 06:00:00
TS_AT_LOCAL 2017-01-01 06:00:00 -05:00
TS_AT_DB 2017-01-01 05:00:00 US/CENTRAL
TS_AT_SESSION 2017-01-01 06:00:00 -05:00
date
, how do you know it has 'regional' times, and how would Oracle know what region/offset it represents - and so how to convert it to UTC? Do you have other information that identifies which region each value is supposed to be in? – Bicentennial