In ICS Definitive Guide #2 we looked at the scheduling of integrations and mentioned the possibility of using iCal. In this tip we shall explore advanced iCal facility for defining schedules within ICS.
The iCal format is probably best known for sharing meeting events in tools such as outlook. The format is actually a standard defined by the IETF originally in 1998 (https://www.ietf.org/rfc/rfc2445.txt) and updated several times the latest being 2015 (https://tools.ietf.org/html/rfc7529). The goal of the definition has been for the purpose of driving standardisation across PIM tools (Personal Information Management) tools which includes Outlook and Thunderbird etc. It is a substantial standard the original document ran to 150 pages, but the section supported by the schweduler’s advanced option purely relates to the reoccurence definition covered by section 4.3.10 of the original RFC, and only takes five pages. If you want to know lots about iCal and the varying revisions then you may find https://icalendar.org/ helpful.
It is worth mentioning that today ICS under the hood exploits Oracle’s Enterprise Scheduler Service (ESS). ESS documentation identifies that it works to the 2445 version of the specification (see here). ESS became a 1st class citizen component with the start of the 12c middleware product stack. As a result, if you see any errors processing an iCal configuration the error codes will reference ESS does.
So why support for this part of the iCal standard. Well unlike the UI provided, the FREQ definition with all the elements of the definition that can be provided mean some very sophisticated schedules can be defined. For example you could create a definition that says the scheduler should only trigger 9.15, 9.30, 14.15, 14.30 on Wednesdays for week numbers 7, 8, 21 and 49.
Syntax
For ease of reference, the definition of how a FREQ element should be created is, according for RFC2445:
“FREQ”=freq *(
; either UNTIL or COUNT may appear in a ‘recur’,
; but UNTIL and COUNT MUST NOT occur in the same ‘recur’( “;” “UNTIL” “=” enddate ) /
( “;” “COUNT” “=” 1*DIGIT ) /; the rest of these keywords are optional,
; but MUST NOT occur more than once( “;” “INTERVAL” “=” 1*DIGIT ) /
( “;” “BYSECOND” “=” byseclist ) /
( “;” “BYMINUTE” “=” byminlist ) /
( “;” “BYHOUR” “=” byhrlist ) /
( “;” “BYDAY” “=” bywdaylist ) /
( “;” “BYMONTHDAY” “=” bymodaylist ) /
( “;” “BYYEARDAY” “=” byyrdaylist ) /
( “;” “BYWEEKNO” “=” bywknolist ) /
( “;” “BYMONTH” “=” bymolist ) /
( “;” “BYSETPOS” “=” bysplist ) /
( “;” “WKST” “=” weekday ) /( “;” x-name “=” text )
)freq = “SECONDLY” / “MINUTELY” / “HOURLY” / “DAILY”/ “WEEKLY” / “MONTHLY” / “YEARLY”
enddate = date
enddate =/ date-time ;An UTC value
byseclist = seconds / ( seconds *(“,” seconds) )
seconds = 1DIGIT / 2DIGIT ;0 to 59
byminlist = minutes / ( minutes *(“,” minutes) )
minutes = 1DIGIT / 2DIGIT ;0 to 59
byhrlist = hour / ( hour *(“,” hour) )
hour = 1DIGIT / 2DIGIT ;0 to 23
bywdaylist = weekdaynum / ( weekdaynum *(“,” weekdaynum) )
weekdaynum = [([plus] ordwk / minus ordwk)] weekday
plus = “+”
minus = “-”
ordwk = 1DIGIT / 2DIGIT ;1 to 53
weekday = “SU” / “MO” / “TU” / “WE” / “TH” / “FR” / “SA”
;Corresponding to SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
;FRIDAY, SATURDAY and SUNDAY days of the week.bymodaylist = monthdaynum / ( monthdaynum *(“,” monthdaynum) )
monthdaynum = ([plus] ordmoday) / (minus ordmoday)
ordmoday = 1DIGIT / 2DIGIT ;1 to 31
byyrdaylist = yeardaynum / ( yeardaynum *(“,” yeardaynum) )
yeardaynum = ([plus] ordyrday) / (minus ordyrday)
ordyrday = 1DIGIT / 2DIGIT / 3DIGIT ;1 to 366
bywknolist = weeknum / ( weeknum *(“,” weeknum) )
weeknum = ([plus] ordwk) / (minus ordwk)
bymolist = monthnum / ( monthnum *(“,” monthnum) )
monthnum = 1DIGIT / 2DIGIT ;1 to 12
bysplist = setposday / ( setposday *(“,” setposday) )
setposday = yeardaynum
Applying the syntax to get complex schedules
With all of that you have if careful all the information to create the most complex schedules you like. To illustrate here is a validating example:
FREQ=YEARLY;INTERVAL=3;BYMONTH=5;BYDAY=2,7;
This translates to a schedule triggering every 3 years on May 2nd and 7th. As you can see trying to express this using calendars and menus would probably prove to be fairly complex. But pretty simple in text once the notation is understood.
We should address a couple of challenges that exist.
Avoiding the traps
Firstly (the current ICS documentation here) shows the example expression as:
FREQ=MONTHLY;BYMONTHDAY=1,10,15;BYHOUR=5,10,15,20;BYMINUTE=15
However the example omits a key terminating semi colon (essentially each part of the expression needs to be terminated by a semi colon). So, the correct representation is:
FREQ=MONTHLY;BYMONTHDAY=1,10,15;BYHOUR=5,10,15,20;BYMINUTE=15;
Whilst not too serious, an easy mistake to make. Unfortunately today the error messages from ESS back to ICS are rather uninformative with an error message and code of
ESS-09402 Failed to compile recurrence expression
So if you see this error, our advise is to simplify the expression or build it up a piece at a time if you can.
The last issues we have yet to understand relate to the definitions support for extension attributes shown as x-name in the specification. Well to be honest, this is not important as ICS and ESS do not appear to have any extension elements. The slightly more troubling question, which we have yet to get to the bottom of, is the support for COUNT in the expression which does not appear to be accepted.
OICUser
How to schedule for Business days based on say UK calendar. Is there a away?
Phil Wilkins
Yes it is possible. It is done through setting the time zone checkout https://blogs.oracle.com/integration/timezone-functionality-in-oic-schedules
OICUser
How can I schedule the integration to ensure it doesnt run on a public holiday? For e.g., an integration scehduled to run on last Fri of the month should instead run on last thursday of the month in case the last friday of the month is a public holiday in say USA.
Phil Wilkins
The key is whether you can express as a formula the public holidays
OICUser
Can’t think of anyway to define the public holidays in the form of a formula.
Phil Wilkins
In which case you’ll not be able to encode it into a schedule. We’d suggest running a 2nd schedule that triggers for the months which might need an alternate day. Then when the integration runs it looks up to a DB table to work out if needs to run or not
OIC
Is it possible to schedule an integration on say 1st workday of a month? Or say last workday of the month? (Irresepective of whether or not the first workday is a public holiday) For e.g., 1st workday of Jul 2021 would be on Thu but 1st workday of June would be Tuesday.
Phil Wilkins
Here is an explanation of how to do it https://medium.com/scrubbi/creating-a-google-calendar-event-that-repeats-on-the-first-weekday-of-every-month-9ca0113eedea
OIC User
Is it possible to schedule a run on the 6th day after month end close, which will be different for all the months for different years? OIC does not allow more than 5 recurrences in iCal.
Phil Wilkins
This is a common question. As month end varies unless you can express a relatively simple formula then ical can’t help you. We’ll blog about the options soon. But essentially either keep a DB of month end dates, or in your case month end + 6. Then the start of the integration check to see if it is a correct date when the scheduler triggers if it is then continue otherwise stop. If you can derive the date, then use FaaS to determine dates is valid and then calculates and sets a schedule for next month end using a 1 off schedule
OICUser
Is it possible to create an ICAL schedule like below
Jan – 12th to 31st
Feb- 1st to 6th
April – 12th to 30th
May – 1st to 6th
july – 12th to 31st
Aug – 1st to 6th
Oct – 12th to 31st
Nov – 1st to 6th
Thanks
Phil Wilkins
That looks like a complex repeating pattern – checkout https://oracle-integration.cloud/2021/08/26/oic-scheduling-for-end-of-month-style-processes-tip-11/
OICUser
Thank you Phil for the promt response. I was wondering if I can have 2 FREQs defined in the same iCAL expression. 1 for Jan, Apr, Jul, Oct where the Days will be 12 to 31 and the other for rest of the months where Days will be 1 to 6. Is it possible to have two schedules like this?
Sanjay
Hi Phil
Is it possible to schedule an integration to run every 30 minutes between first and fourth weekday of every month?
Thanks
Sanjay
Phil Wilkins
You want something like this – FREQ=MONTHLY;BYSETPOS=1;BYDAY=MO;INTERVAL=1. Have a look at tip 11. There are a couple of tools that could help formulate the expression
chandra MAdasi
Hi
Do you have example of excluding the holidays list .
Appreciate your help
Regards,
Phil Wilkins
Because holidays don’t always follow a formula that can be easily expressed this extraordinarily difficult to define and test. We have written about this before and the recommendation has been to implement a lookup and filter
OIC Developer
Hello Phil,
Can we schedule OIC integrations with the following schedules –
1. 10th Business day of month (Eg. 8/14/2023, 9/14/2023, 10/13/2023)
2. 23rd day of month without weekends (Eg. 8/31/2023, 1/31/2024, 5/31/2024)
3. 7th Tuesday after quarter ends (Eg.8/15/2023, 11/14/2023)
Thanks
Phil Wilkins
1 & 2 in your question can be done. Point 3, isn’t so easy, and I’d suggest the easiest way to address this is to have a trigger for every Tuesday, then within the integratiuon it works out whether that is the 7th Tuesday after the Qtr – if it is invoke the integration otherwise just stop.
Kels
If we want to shedule OIC integration on wednesday, then next week monday, then next week wednesday. Please see below dates.
Jan -> 18 THU, 22 MON
Feb -> 1 THU, 5 MON, 15 THU, 19 MON, 29 THU
MAR -> 5 MON, 14 THU, 18 MON, 28 THU
APR -> 1 MON and so on.
How can we schedule it using Ical expression ?
Robert van Molken
To represent a recurring event for every Monday and Wednesday of the week in iCal format, you can use the RRULE (Recurrence Rule) property.
Here’s an example of how you can express this:
BEGIN:VEVENT
SUMMARY:Your Event Name
RRULE:FREQ=WEEKLY;BYDAY=MO, TH
DTSTART:20240113T090000Z
DTEND:20240113T100000Z
LOCATION:Your Event Location
DESCRIPTION:Description of your event
END:VEVENT
In this example:
You would replace the placeholders with your specific event details, and you can adjust the DTSTART and DTEND values to match the start and end times of your event.
Kels
We need to execute our OIC shceduler alternet Monday and alternet Thrusday as per date mentioned, not Monday and Thrusday every week.