Auto Sync Personal Calendar Events to Work Google Calendar

Charles Bai
3 min readApr 1, 2022

Problem

Do you have two Google calendars to keep your life and work events separated? If so, you’re like me. I want to keep my personal calendar synced with my work calendar, so that people who want to schedule meetings with me using my work Calendly link won’t accidentally block times that conflicts my personal events.

My personal calendar is also subscribed to multiple other calendars, and I have quite a few events I marked as “tentative / maybe” for attending, which I attend based on my availabilities.

My struggle is that all existing tools, like Zapier or ReclaimAI, are not customizable enough. All events are synced to my work calendar, regardless of the status (going / maybe / rejected). Often I also need to pay premium to mask out the details of my personal events when they are synced.

Solution

I did a bit of digging and found out about Google App Script and this post. I worked on top of what Will Roman wrote and quickly hacked together a script. Code is not elegant but it wroks ;)

What it does is:

  1. Automatically pull all your personal events and create blocks on your work calendar. The events will only be pulled if (a) they not all day events (b) you are owner or you are invited and have marked as “going / yes”.
  2. If you have multiple personal events that start and end at the exact same time, it will only create one block on your work cal.
  3. If you have a personal event and a work event that start and end at the exact same time, it won’t create any blocks on your work cal.
  4. Automatically delete and recreate blocks on work calendar when you make changes to your personal calendar.

Example

On the left hand side is my personal cal and the right hand side is my work cal. On Thursday, my 11am event and my 2:15pm are not synced. One is a subscribed event from a community cal and the other one a direct invite but I marked as “tentative / maybe”. On Friday, my all day event “Pay rent” is not synced.

Script

function sync() {
const personalBlockName = 'Personal Busy'; // Name your block name
const totalNumOfDays = 30; // Number of days to sync
var today = new Date();
var enddate = new Date();
enddate.setDate(today.getDate() + totalNumOfDays);
var workCal = CalendarApp.getDefaultCalendar(); // TODO: Fill in your personal calendar ID
var personalCal = CalendarApp.getCalendarById(<PERSONAL_CAL_ID>);
var personalEvents = personalCal.getEvents(today, enddate);
var workEvents = workCal.getEvents(today, enddate);
personalEvents = personalEvents.filter(event => !event.isAllDayEvent());
personalEvents = personalEvents.filter(event => !(event.getMyStatus() && event.getMyStatus().toString() != "YES"));
var timeObjTupleList = personalEvents.map(event => [event.getStartTime(), event.getEndTime()]);
timeObjTupleList = timeObjTupleList.filter(
(event, index, array) => array.findIndex(t => t[0].getTime() == event[0].getTime() && t[1].getTime() == event[1].getTime()) == index
);
// Remove deleted personal events from work cal
var existingPersonalBusyEvents = workEvents.filter(event => event.getTitle() == personalBlockName);
existingPersonalBusyEvents.forEach(function (existingPersonalBusyEvent, i) {
const existingPersonalBusyTimeObjTuple = [existingPersonalBusyEvent.getStartTime(), existingPersonalBusyEvent.getEndTime()];
var notBusyAnymore = timeObjTupleList.find(t => {
return t[0].getTime() == existingPersonalBusyTimeObjTuple[0].getTime() && t[1].getTime() == existingPersonalBusyTimeObjTuple[1].getTime();
}) == undefined;
if (notBusyAnymore) {
existingPersonalBusyEvent.deleteEvent();
}
});
// Go through filtered personal cal events and add to work cal
timeObjTupleList.forEach(function (timeObjTuple, i) {
const startTime = timeObjTuple[0];
const endTime = timeObjTuple[1];
var timeAlreadyBusy = workEvents.find(el => {
return el.getStartTime().getTime() == startTime.getTime() && el.getEndTime().getTime() == endTime.getTime();
}) != undefined;
if (!timeAlreadyBusy) {
var newEvent = workCal.createEvent(personalBlockName, startTime, endTime);
newEvent.removeAllReminders();
}
});
}

How to deploy?

Follow Will’s post, it’s very intuitive. The only thing you need to change is to use the script I provided above. Note that you will need to fill in your personal Google Cal ID in the script. I marked it as “TODO”.

Cheers!

--

--