/events should return ALL exceptions to recurring events (instead /calendarView)

/events should return ALL exceptions to recurring events (instead /calendarView)
1

Upvotes

Upvote

 Aug 16 2022
1 Comments (1 New)
New

 

Background: When exceptions are made to recurring events Outlook makes a separate exception appointment, but does not return that appointment in the /events API. Instead you're forced to query the /calendarView API with date ranges to look for exceptions to the recurrence pattern of an event. This demands multiple API calls to every recurring event just to test whether or not exceptions exist. This is like a technical game of "Where's Waldo" for any recurring event that has an exception, which is bad if there is a recurring event that has no ending. 

Example

 

 

alodish_0-1660592707509.png

 

 

This screenshot of my test calendar shows a situation where an occurrence of a recurring event has broken the recurrence pattern of the series master. In this case, my Monday morning meeting was moved to Tuesday due to a national holiday. This type of situation is common and will likely present itself hundreds if not thousands of times as we compile our database. 

 

An API call to the events resource fails to capture this event. 

 

The call: https://graph.microsoft.com/v1.0/me/calendars/{test calendar id}/events

 

The response:

{

    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('2adf871d-4f40-4e83-98f2-d6e4ea07313b')/calendars('AAMkADEyYTAyY2YzLTI5NTAtNDI5Ni04NWQ2LWMxZWQzMjQ1NTdiYwBGAAAAAAAm5EBbdk2kQLjc8O4qX905BwCfkUvXF2nyQ5Ac5rmmjk-UAAAAAAEGAACfkUvXF2nyQ5Ac5rmmjk-UAAAC_2WgAAA%3D')/events",

    "value": [

        {

            "@odata.etag": "W/\"n5FL1xdp8kOQHOa5po5P1AAAWQhJng==\"",

            "id": "[omitted]",

            "createdDateTime": "2022-06-15T16:56:49.2346883Z",

            "lastModifiedDateTime": "2022-06-15T16:58:50.0089411Z",

            "changeKey": "n5FL1xdp8kOQHOa5po5P1AAAWQhJng==",

            "categories": [],

            "transactionId": null,

            "originalStartTimeZone": "UTC",

            "originalEndTimeZone": "UTC",

            "iCalUId": "[omitted]",

            "reminderMinutesBeforeStart": 1080,

            "isReminderOn": true,

            "hasAttachments": false,

            "subject": "Recurring Event",

            "bodyPreview": "",

            "importance": "normal",

            "sensitivity": "normal",

            "isAllDay": true,

            "isCancelled": false,

            "isOrganizer": true,

            "responseRequested": true,

            "seriesMasterId": null,

            "showAs": "free",

            "type": "seriesMaster",

            "webLink":"[omitted]",

            "onlineMeetingUrl": null,

            "isOnlineMeeting": false,

            "onlineMeetingProvider": "unknown",

            "allowNewTimeProposals": true,

            "isDraft": false,

            "hideAttendees": false,

            "onlineMeeting": null,

            "responseStatus": {

                "response": "none",

                "time": "0001-01-01T00:00:00Z"

            },

            "body": {

                "contentType": "html",

                "content": "[omitted]"

            },

            "start": {

                "dateTime": "2022-07-18T00:00:00.0000000",

                "timeZone": "UTC"

            },

            "end": {

                "dateTime": "2022-07-19T00:00:00.0000000",

                "timeZone": "UTC"

            },

            "location": {

                "displayName": "",

                "locationType": "default",

                "uniqueIdType": "unknown",

                "address": {},

                "coordinates": {}

            },

            "locations": [],

            "recurrence": {

                "pattern": {

                    "type": "weekly",

                    "interval": 1,

                    "month": 0,

                    "dayOfMonth": 0,

                    "daysOfWeek": [

                        "monday"

                    ],

                    "firstDayOfWeek": "sunday",

                    "index": "first"

                },

                "range": {

                    "type": "endDate",

                    "startDate": "2022-07-18",

                    "endDate": "2023-01-02",

                    "recurrenceTimeZone": "Eastern Standard Time",

                    "numberOfOccurrences": 0

                }

            },

 

Discussion

The response above is of the only object pertaining to the recurring event “Recurring Event” in my test calendar. The response contains no information regarding the existence of exceptions, let alone the exceptions themselves. I’ve been told that this resource is functioning as intended and in order to receive exceptions I will need to use a different resource. 

 

The resource “List instances” was recommended previously, but I believe this to be the least efficient way to handle the task at hand as this resource is limited to only a single series master event per API call. If we have 10’s of thousands of recurring events, a separate call for each of their instances would be highly inefficient.

 

The resource, “Calendar view”, is a more efficient option in my opinion as it is not limited by event. That’s not to say it doesn’t have limitations.

 

For example:

  • It needs to be filtered to avoid the retrieval of redundant event data
    • …/calendarView…&$filter=type eq ‘exception’
  •  It requires a window of time to be specified
  • The window of time cannot exceed 1825 days (5 years)

 

While calendar view certainly captures far more exceptions per API call than list instances, it is still inefficient and fails to accomplish telling the entire story of a particular calendar.

 

Question Summary

Why aren’t exceptions included in the call to the /events resource?

From what I have gathered, occurrences aren’t included in the call to /events due to the possibility of a recurring event persisting indefinitely. The events call captures all events in a calendar and therefore could not retrieve occurrences to a recurring event with no end date. While that makes sense, it is impossible for exceptions to do the same.

 

 

 

Comments
Copper Contributor

Even more difficult are deletion exceptions. At least with modified instance you can see something when you look at instances.

 

With a deleted instance, as near as I can tell, you have to 

  • manually calculate a list of recurrences from the recurrence pattern
  • fetch instance data
  • compare the lists, looking for missing instances

Yikes!

 

It would be extremely helpful, in the recurring appointment, to have exception information:

  • which instances have been deleted
  • which instances have been altered