Skip to content
Advertisement

Different results for TO_TIMESTAMP_TZ and CAST AS TIMESTAMP WITH LOCAL TIME ZONE in Oracle DB

I have an Oracle 11g database and I’m trying to experiment with how DST is handled with TIMESTAMP datatypes (especially ones created from incoming data that doesn’t have a time zone included). I’m seeing a difference in behavior when using TO_TIMESTAMP_TZ() vs CAST(DATE as TIMESTAMP WITH LOCAL TIME ZONE) that I can’t explain. I would expect that the resulting datatype is a zoned timestamp regardless of how it is created and any operation on it would be identical but it does not appear that this is the case.

Any idea why when using the CAST option the “extra” hour created by the Fall DST change isn’t being taken into account in the INTERVAL math? I would expect both rows of the query below to be identical.

Query:

select to_timestamp_tz('11/1/2015 1:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR') + interval '2' hour as DST_PLUS_2, -- this is a post DST jump time
       to_timestamp_tz('11/1/2015 12:59 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR') + interval '2' hour as PRE_DST_PLUS_2, -- this is a pre DST jump time
       to_char(to_timestamp_tz('11/1/2015 1:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR'), 'TZR') as TZR
  from dual
union all
select cast(to_date('11/1/2015 1:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone) + interval '2' hour as DST_PLUS_2,
       cast(to_date('11/1/2015 12:59 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone) + interval '2' hour as PRE_DST_PLUS_2,
       to_char(cast(to_date('11/1/2015 1:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone), 'TZR') as TZR
  from dual;

Results:

DST_PLUS_2                                  PRE_DST_PLUS_2                              TZR
01-NOV-15 03.00.00.000000000 AM US/PACIFIC  01-NOV-15 01.59.00.000000000 AM US/PACIFIC  US/PACIFIC
01-NOV-15 03.00.00.000000000 AM US/PACIFIC  01-NOV-15 02.59.00.000000000 AM US/PACIFIC  US/PACIFIC

Advertisement

Answer

It looks like this comes down to the fact that TO_TIMESTAMP_TZ attempts to infer the TZD element of the TIMESTAMP from the date while CAST AS TIMESTAMP WITH LOCAL TIME ZONE will take the current TZD of the database regardless of when the date is. Or they just have different default behaviors for picking which of the 1AM times (pre or post time change) to choose. This difference in behavior is causing the resulting hour to be different by one.

Thanks ruudvan!

Query:

select to_char(to_timestamp_tz('11/1/2015 1:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR'), 'TZD') as TZD_TO_TS_TZ_1,
       to_char(cast(to_date('11/1/2015 1:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone), 'TZD') as TZD_CAST_1,
       to_char(to_timestamp_tz('11/1/2015 12:00 AM US/Pacific', 'MM/DD/YYYY HH:mi AM TZR'), 'TZD') as TZD_TO_TS_TZ_12,
       to_char(cast(to_date('11/1/2015 12:00 AM', 'MM/DD/YYYY HH:mi AM') as timestamp with local time zone), 'TZD') as TZD_CAST_12
  from dual;

Results:

TZD_TO_TS_TZ_1  TZD_CAST_1  TZD_TO_TS_TZ_12 TZD_CAST_12
PST             PDT         PDT             PDT
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement