Creating a Dynamic Calendar Feed

Jordan HolmerJordan Holmer
4 min read

In this blog, I will discuss how to provide dynamic calendar feeds for users in Oracle APEX using ORDS.

Why Build a Dynamic Calendar Feed?

My app offers faculty a calendar feature to view their teaching schedules. The APEX component allows exporting to iCal, and many users like adding their schedules to their device's calendar app. The issue is that the data is static. If the schedule changes, the calendar apps won't show the latest information. For instance, if a teacher needs to substitute for another class, it won't appear in their calendar app. To fix this, we need to use an internet calendar subscription.

What is an Internet Calendar?

An Internet Calendar (or calendar subscription) is a link that allows users to add a live calendar to their personal calendar apps. It updates automatically with new events. This is often used for schedules, team events, or public calendars and is supported by most major apps like Google Calendar, Outlook, and Apple Calendar.

The .ics file format (iCalendar) is a standard format used for these feeds. It includes event details like title, date, time, location, and recurrence, and it works well across different platforms. In this blog, I won't go into the details of the .ics format, but I will explain how to offer users a dynamic feed.

My Approach

The first step was to generate the content of the .ics file based on a teacher’s unique schedule. The following function will then be called anytime a refresh of the calendar data is requested by the calendar app.

CREATE OR REPLACE FUNCTION generate_ics_file_teacher_schd (
   p_teacher_id   IN NUMBER)
   RETURN CLOB
IS
   l_ics CLOB := 'BEGIN:VCALENDAR' || CHR(13) ||
                 'VERSION:2.0' || CHR(13) ||
                 'X-WR-CALNAME:Class Schedule' || CHR(13) ||
                 'X-PUBLISHED-TTL:PT1H' || CHR(13);
BEGIN
   FOR r IN (
     SELECT event_title, event_start, event_end, location, uid
     FROM teacher_calendar_events
     WHERE teacher_id = p_teacher_id
   ) LOOP
     l_ics := l_ics || 'BEGIN:VEVENT' || CHR(13) ||
                      'UID:' || r.uid || CHR(13) ||
                      'DTSTAMP:' || TO_CHAR(SYSDATE, 'YYYYMMDD"T"HH24MISS"Z"') || CHR(13) ||
                      'DTSTART:' || TO_CHAR(FROM_TZ(CAST(r.event_start AS TIMESTAMP), 'America/Chicago') AT TIME ZONE 'UTC',
                                            'YYYYMMDD"T"HH24MISS"Z"') || CHR(13) ||
                      'DTEND:' || TO_CHAR(FROM_TZ(CAST(r.event_end AS TIMESTAMP), 'America/Chicago') AT TIME ZONE 'UTC',
                                          'YYYYMMDD"T"HH24MISS"Z"') || CHR(13) ||
                      'SUMMARY:' || r.event_title || CHR(13) ||
                      CASE
                        WHEN r.location IS NOT NULL THEN 'LOCATION:' || r.location || CHR(13)
                        ELSE ''
                      END ||
                      'END:VEVENT' || CHR(13);
   END LOOP;
   l_ics := l_ics || 'END:VCALENDAR';
   RETURN l_ics;
END;

Next, I created a module and resource handler in RESTful Services.

The Source Type is set to PL/SQL. Using PL/SQL gives you the ability to set specific headers needed for .ics files, particularly the Content-Type header as text/calendar. This is essential to ensure that calendar applications recognize the response as a calendar file.

Below is the Source:

DECLARE
   l_ics_content   CLOB;
BEGIN
   HTP.init;

   OWA_UTIL.mime_header ('text/calendar', FALSE);
   OWA_UTIL.http_header_close;

   l_ics_content := generate_ics_file_teacher_schd (:id);

   HTP.PRINT (l_ics_content);
END;

Lastly, I removed the iCal export option from the calendar component in my APEX app. Instead, I provided a popup with instructions for users on how to subscribe to their personal calendar feed.

The URL can now be used in most major calendar apps to subscribe to a personal class schedule that can be updated. Now when I am scheduled for a dreaded substitution assignment, it appears directly in my calendar app.

Conclusion

Creating a dynamic calendar feed using APEX and ORDS has been an interesting project that taught me a lot about both the potential and limitations of these tools. One key consideration was managing the amount of data served by ORDS.

Pro Tip: To maintain steady performance, I implemented a rolling date range that shows only the most relevant events—the past 7 days and the upcoming 60—ensuring users receive timely, up-to-date information without overwhelming ORDS or their calendar apps.

While I thought about adding alerts to the calendar feed, I realized it might not add much value since many calendar apps have notifications turned off for subscribed calendars by default. This keeps the feed focused on delivering relevant events without overwhelming users with reminders.

Through this experience, I learned how powerful ORDS and RESTful services are for delivering dynamic, user-centered content. They allowed me to build a flexible, live-updating calendar feed that’s easy to share across platforms. If you’re interested in building a similar feature, I highly encourage you to try creating your own dynamic calendar feed using APEX and ORDS. With the flexibility and control of PL/SQL and RESTful services, you can create highly personalized and useful features that enhance the user experience in ways static data just can't match.

2
Subscribe to my newsletter

Read articles from Jordan Holmer directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jordan Holmer
Jordan Holmer

Jordan Holmer is a database administrator and computer science teacher based in New Orleans. With a background in creating database applications using Oracle APEX, he specializes in designing efficient, user-focused solutions that bridge complex data and real-world functionality.