How to schedule an Oracle dbms_scheduler Job timezone and DST safely

Javo picture Javo · Jan 15, 2014 · Viewed 24.5k times · Source

I am trying to setup a DBMS_SCHEDULER Job to run exactly at 1 AM on 1st of January every year on Oracle 11g. How to setup its attributes to be absolutely sure it wont get executed in wrong hour, because of timezone differences nor Daylight Savings Time.

I have spent plenty of time going through Oracle documentation, but I have still not reached the level of certainity.

Just btw, here are the rules which I found and consider relevant to the subject:

Job attributes

start_date This attribute specifies the first date on which this job is scheduled to start. If start_date and repeat_interval are left null, then the job is scheduled to run as soon as the job is enabled. For repeating jobs that use a calendaring expression to specify the repeat interval, start_date is used as a reference date. The first time the job will be scheduled to run is the first match of the calendaring expression that is on or after the current date. The Scheduler cannot guarantee that a job will execute on an exact time because the system may be overloaded and thus resources unavailable.

repeat_interval This attribute specifies how often the job should repeat. You can specify the repeat interval by using calendaring or PL/SQL expressions. The expression specified is evaluated to determine the next time the job should run. If repeat_interval is not specified, the job will run only once at the specified start date. See "Calendaring Syntax" for further information.

Rules in Calendaring syntax

  • The calendaring syntax does not allow you to specify a time zone. Instead the Scheduler retrieves the time zone from the start_date argument. If jobs must follow daylight savings adjustments you must make sure that you specify a region name for the time zone of the start_date. For example specifying the start_date time zone as 'US/Eastern' in New York will make sure that daylight saving adjustments are automatically applied. If instead the time zone of the start_date is set to an absolute offset, such as '-5:00', daylight savings adjustments are not followed and your job execution will be off by an hour half of the year.
  • When start_date is NULL, the Scheduler will determine the time zone for the repeat interval as follows:
  • It will check whether the session time zone is a region name. The session time zone can be set by either: Issuing an ALTER SESSION statement, for example: SQL> ALTER SESSION SET time_zone = 'Asia/Shanghai'; Setting the ORA_SDTZ environment variable.
  • If the session time zone is an absolute offset instead of a region name, the Scheduler will use the value of the DEFAULT_TIMEZONE Scheduler attribute. For more information, see the SET_SCHEDULER_ATTRIBUTE Procedure.
  • If the DEFAULT_TIMEZONE attribute is NULL, the Scheduler will use the time zone of systimestamp when the job or window is enabled.

Answer

Catalin Filip picture Catalin Filip · Mar 27, 2014

You may use this to make sure you pass a timestamp with time zone and that the start date will have a timezone name (US/Eastern) instead of an offset (ex: +5:00). This way, as the above fragments from the oracle docs mention, the Scheduler will keep track of DST.

-- Create a SCHEDULE

declare 
 v_start_date timestamp with time zone;
BEGIN 

select localtimestamp at time zone 'US/Eastern' into v_start_date from dual; --US/Eastern

DBMS_SCHEDULER.CREATE_SCHEDULE(
      schedule_name => 'SAMPLE_SCHEDULE',
      start_date => v_start_date,
      repeat_interval => 'FREQ=DAILY; BYHOUR=10; BYMINUTE= 15',
      comments => 'Runs daily at the specified hour.'); 
END;

To make sure you have set it properly you can run this: ALTER SESSION SET nls_timestamp_tz_format = 'MM-DD-YYYY HH24:MI:SS tzr tzd';

Now, create two schedules, one as above and one using sysdate as the start_date parameter and execute the query below.

-- Check the TIMEZONE 
select * from USER_SCHEDULER_SCHEDULES;


v1:
27-MAR-14 11.44.24.929282 AM **US/EASTERN**

v2:

27-MAR-14 05.44.54.000000 PM **+05:00**