How to Write Scheduler Calendar Expressions in Oracle

Describe when Scheduler jobs repeat with FREQ, INTERVAL, and BY clauses, and test the run dates before you schedule anything.

The REPEAT_INTERVAL of a Scheduler job is a calendar expression: a frequency, an interval, and BY clauses that pick months, days, hours, and minutes. DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING computes the run dates an expression produces, so you can test it before giving it to a job.

Code for This Guide

The main examples are in the examples/pkg-scheduler folder of the Oracle Database 26ai code repository on GitHub, each with its output. They use NIMBUS, the sample schema of a fictional airline, which you can install with the scripts in the setup/nimbus folder.

They come from Oracle Database 26ai SQL and PL/SQL Book.

Syntax

FREQ=YEARLY | MONTHLY | WEEKLY | DAILY | HOURLY | MINUTELY | SECONDLY
  [; INTERVAL=n]
  [; BYMONTH=...] [; BYMONTHDAY=...] [; BYDAY=...] [; BYDATE=MMDD,...]
  [; BYHOUR=...] [; BYMINUTE=...] [; BYSETPOS=...]

dbms_scheduler.evaluate_calendar_string(calendar, start_date, return_date_after,
                                        next_run_date_out);

Test Common Expressions

SHOW prints the next three run dates of an expression, starting on Sunday 15 March 2026 at 09:00 in Dubai.

Example:

declare
  v_start timestamp with time zone := timestamp '2026-03-15 09:00:00 Asia/Dubai';
  procedure show (p_calendar varchar2) is
    v_next timestamp with time zone := v_start;
  begin
    dbms_output.put_line(p_calendar);
    for i in 1 .. 3 loop
      dbms_scheduler.evaluate_calendar_string(p_calendar, v_start, v_next, v_next);
      dbms_output.put_line('  ' || to_char(v_next, 'Dy DD-MON-YYYY HH24:MI'));
    end loop;
  end;
begin
  show('FREQ=HOURLY; INTERVAL=4');
  show('FREQ=WEEKLY; BYDAY=MON,FRI; BYHOUR=6; BYMINUTE=0');
  show('FREQ=MONTHLY; BYMONTHDAY=-1; BYHOUR=23');            -- last day of the month
  show('FREQ=MONTHLY; BYDAY=1SUN; BYHOUR=4');                -- first Sunday
  show('FREQ=YEARLY; BYDATE=0101,0701; BYHOUR=0');
end;
/

Output:

FREQ=HOURLY; INTERVAL=4
  Sun 15-MAR-2026 13:00
  Sun 15-MAR-2026 17:00
  Sun 15-MAR-2026 21:00
FREQ=WEEKLY; BYDAY=MON,FRI; BYHOUR=6; BYMINUTE=0
  Mon 16-MAR-2026 06:00
  Fri 20-MAR-2026 06:00
  Mon 23-MAR-2026 06:00
FREQ=MONTHLY; BYMONTHDAY=-1; BYHOUR=23
  Tue 31-MAR-2026 23:00
  Thu 30-APR-2026 23:00
  Sun 31-MAY-2026 23:00
FREQ=MONTHLY; BYDAY=1SUN; BYHOUR=4
  Sun 05-APR-2026 04:00
  Sun 03-MAY-2026 04:00
  Sun 07-JUN-2026 04:00
FREQ=YEARLY; BYDATE=0101,0701; BYHOUR=0
  Wed 01-JUL-2026 00:00
  Fri 01-JAN-2027 00:00
  Thu 01-JUL-2027 00:00

PL/SQL procedure successfully completed.
  • INTERVAL=4 with FREQ=HOURLY runs every four hours from the start time.
  • BYDAY=MON,FRI picks two days a week, at the hour and minute given.
  • BYMONTHDAY=-1 counts from the end: the last day of each month.
  • BYDAY=1SUN is the first Sunday of each month, and BYDATE picks fixed dates.

Business Hours, Last Weekday, Fixed Days

Example:

declare
  v_start timestamp with time zone := timestamp '2026-03-15 09:00:00 Asia/Dubai';
  procedure show (p_calendar varchar2) is
    v_next timestamp with time zone := v_start;
  begin
    dbms_output.put_line(p_calendar);
    for i in 1 .. 3 loop
      dbms_scheduler.evaluate_calendar_string(p_calendar, v_start, v_next, v_next);
      dbms_output.put_line('  ' || to_char(v_next, 'Dy DD-MON-YYYY HH24:MI'));
    end loop;
  end;
begin
  -- every 15 minutes, only from 9 to 17 on weekdays
  show('FREQ=MINUTELY; INTERVAL=15; BYHOUR=9,10,11,12,13,14,15,16; '
       || 'BYDAY=MON,TUE,WED,THU,FRI');
  -- the last weekday of each month
  show('FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; BYSETPOS=-1; BYHOUR=18; BYMINUTE=0');
  -- the 1st and 15th of each month
  show('FREQ=MONTHLY; BYMONTHDAY=1,15; BYHOUR=7; BYMINUTE=30');
end;
/

Output:

FREQ=MINUTELY; INTERVAL=15; BYHOUR=9,10,11,12,13,14,15,16; BYDAY=MON,TUE,WED,THU,FRI
  Mon 16-MAR-2026 09:00
  Mon 16-MAR-2026 09:15
  Mon 16-MAR-2026 09:30
FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; BYSETPOS=-1; BYHOUR=18; BYMINUTE=0
  Tue 31-MAR-2026 18:00
  Thu 30-APR-2026 18:00
  Fri 29-MAY-2026 18:00
FREQ=MONTHLY; BYMONTHDAY=1,15; BYHOUR=7; BYMINUTE=30
  Wed 01-APR-2026 07:30
  Wed 15-APR-2026 07:30
  Fri 01-MAY-2026 07:30

PL/SQL procedure successfully completed.
  • Every 15 minutes, limited by BYHOUR and BYDAY to weekday office hours, so the first run is Monday at 09:00.
  • BYSETPOS=-1 takes the last of the weekdays in each month: the last working day.
  • BYMONTHDAY=1,15 runs twice a month.

Things to Know

  • Times follow the time zone of the start date, so give it a region such as Asia/Dubai.
  • Named schedules and EXCLUDE= clauses can combine calendars, for example to skip holidays.
  • Always test a new expression with EVALUATE_CALENDAR_STRING before it goes into production.

Related Guides

Conclusion

Scheduler calendar expressions describe when a job repeats with FREQ, INTERVAL, and BY clauses. Test each one with EVALUATE_CALENDAR_STRING, use negative values and BYSETPOS for "last" rules, and anchor them in a time zone region.

Get more Vinish.dev tutorials on Google

See my articles more often when you search Google.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted