0

I'm trying to update the recurrence rule on an event in an Apps Script application, similar to changing the end date of the recurrence in the UI and clicking "all events".

I load the first event in the series and run Calendar.Events.patch with the new recurrence rule. The original event has a recurrence rule of 10 occurrences, weekly on Friday. I get no errors, but the returned event is unchanged.

I tried doing the same thing in the API explorer by manually copying my recurrence rule and got the same result — the returned object in the API explorer showed it ran successfully, but didn't actually update the event (the old recurrence rule was still there, instead of the new one). Why is it not failing if it's not accepting the changes?

My only change in the API explorer other than the event and calendar ID:

{
  "recurrence": [
    "RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=20220921T102754Z;BYDAY=FR"
  ]
}

The goal is to have a script that removes bookings from a room resource outside a predefined booking window. The built-in AppsScript methods for RRULEs don't have a clean way to change only the RRULE without getting/setting a lot of other data about the event. We want to be able to set the end date as closely as possible to the end of the window while still following the other set rules for the RRULE.

function cleanRoom() {
  resourceId = "id@resource.calendar.google.com" // this is a test room
  let bulkevents = JSON.parse(Calendar.Events.list("id2@resource.calendar.google.com"));
  let allevents = bulkevents.items.filter(function (e) {
    return e.recurrence != undefined // return all events with a recurrance rule
  });
  console.log('All events with recurrances:\n\n');
  // we want to look at instances of recurring events and filter down to instances more than X days in the future
  for (const x of allevents) {
    const startDT = new Date(x.start.dateTime); // ex. 2022-07-28T07:45:00-05:00
    const title = x.summary;
    // load instances — instances are what shows up on your calendar when you schedule a recurring event. instances are tied to their originator. 
    console.log(title);
    const instances = Calendar.Events.instances(resourceId,x.id);
    for (const i of instances.items) {
      // from the list of instances for an event, find any with an instance after the booking window
      // don't forget to make sure the booking window is correct in config.js
      if (luxon.DateTime.fromISO(i.start.dateTime) > luxon.DateTime.now().plus({ weeks: bookingWindow })) {
        // get the original calendar event so we can edit the end date
        let offendingEvent = Calendar.Events.get(resourceId,i.recurringEventId);
        let rrule = offendingEvent.recurrence[0];
        console.log(rrule);        
        // get last valid date in format
        let correctUntilDate = luxon.DateTime.now().plus({ weeks: bookingWindow });
        // we need to modify the original event / all events
        if (rrule.includes("COUNT")) {
          let regrule = /COUNT=\d\d/;
          let new_rrule = rrule.replace(regrule,'UNTIL='+correctUntilDate.set({seconds: 0}).toFormat("yyyyMMdd'T'HHmmss'Z'"));
          console.log(i);
          console.log(new_rrule);
          const calPatch = {
            recurrence: [new_rrule],
            end: {
              dateTime: i.end.dateTime,
              timeZone: i.end.timeZone
            },
            start: {
              dateTime: i.start.dateTime,
              timeZone: i.start.timeZone
            }
          };
          const result = Calendar.Events.update(calPatch,resourceId,offendingEvent.id);
          
          console.log(result);
          break;
        }
        break; // we don't need to scan every instance of every event; once it's fixed we're done, moving on to the next
      }
    }
  }
}
Ian Hyzy
  • 481
  • 5
  • 26

2 Answers2

1

I tested a few minutes ago with the same request you shared and it did not work, I tested again now and it works, maybe there was an issue before.

If you still have the issue, try changing UNTIL=20220921T102754Z to UNTIL=20220921T102700Z, this worked for me in the API Explorer when I reproduced the same issue you were having. All I changed is seconds from 54 to 00 in UNTIL. Also, if you're still having issues, you can report it through the Issue Tracker.

If this works now in the API Explorer but not with your script please share a minimal example that reproduces the issue.

Lorena Gomez
  • 1,946
  • 2
  • 4
  • 11
  • Thanks for the help, I tried setting seconds to zero but the appscript code is still behaving the same way. I added a code snippet. – Ian Hyzy Sep 07 '22 at 19:00
1

This is just a hunch, but given how PATCH semantics work, I suspect that you're ultimately adding a new rule to the recurrence array, not replacing it in its entirety.

You'll probably have to use PUT semantics instead via the update endpoint. Try experimenting with Calendar.Events.update and see if that works.

TheAddonDepot
  • 8,408
  • 2
  • 20
  • 30
  • calendar.events.update requires setting start/end time, which I'm hoping to avoid (really want to avoid touching as much as possible given how complex dates are), but will try this as a backup. – Ian Hyzy Sep 13 '22 at 16:09
  • Can't you simply reuse the start and end times of the existing event object? – TheAddonDepot Sep 13 '22 at 18:49
  • I added this and have an valid (I think) RRULE as `RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20220927T153900Z;BYDAY=FR` but I'm still getting the issue where the API accepts it but does not update when using the apps script Update method – Ian Hyzy Sep 13 '22 at 20:40
  • I updated the code with what it looks like now – Ian Hyzy Sep 13 '22 at 20:52