Skip to content

Instantly share code, notes, and snippets.

@seshness
Created April 12, 2022 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seshness/9c2b4a53b78c29da314ade9965bd0702 to your computer and use it in GitHub Desktop.
Save seshness/9c2b4a53b78c29da314ade9965bd0702 to your computer and use it in GitHub Desktop.
Syncs your personal calendar with your work calendar as 'busy' events
/**
* Syncs your personal calendar with your work calendar as 'busy' events.
*/
// WARNING: This script has the potential to delete events! Audit the code and run with care.
// The script *should* only delete events it has previously created, but bugs are possible!
// How to use
// ==========
// 1. Share your personal calendar with your work account using the free/busy option.
// 2. Visit https://script.google.com/ and create a new project eg. "Personal calendar sync".
// 3. Uncomment, fill in, and run the line below.
// 4. Set up a scheduled trigger to run the `syncEvents` script every hour.
// Uncomment this line and run to set up state.
// PropertiesService.getUserProperties().setProperty('PERSONAL_EMAIL', '<INSERT PERSONAL EMAIL HERE>');
const daysToSyncPropertyValue = PropertiesService.getUserProperties().getProperty('DAYS_TO_SYNC')
const DAYS_TO_SYNC = daysToSyncPropertyValue ? Number.parseInt(daysToSyncPropertyValue, 10) : 7;
function isWeekend(someDate) {
return someDate.getDay() < 1 || someDate.getDay() > 5;
}
function syncEvents() {
const personalEmail = PropertiesService.getUserProperties().getProperty('PERSONAL_EMAIL');
if (personalEmail == null) {
console.error('No PERSONAL_EMAIL user property set. Save a property in https://developers.google.com/apps-script/reference/properties/properties-service#getUserProperties().')
return;
}
const personalCalendar = CalendarApp.getCalendarById(personalEmail);
const workCalendar = CalendarApp.getDefaultCalendar();
const now = new Date();
const futureDate = new Date(
now.getTime() + DAYS_TO_SYNC * 86400 /* seconds in a day */ * 1000 /* milliseconds in a second */);
const eventsToSync = personalCalendar.getEvents(now, futureDate)
.filter(event => !event.isAllDayEvent())
.filter(event => !isWeekend(event.getStartTime()));
let workEvents = workCalendar.getEvents(now, futureDate);
workEvents = workEvents.filter(workEvent => workEvent.getTag('source') === 'personal-calendar-sync');
const workEventsBySourceId = Object.fromEntries(workEvents.map(workEvent => [workEvent.getTag('source_id'), workEvent]));
let eventsAdded = 0;
let eventsChanged = 0;
let eventsDeleted = 0;
for (let eventToSync of eventsToSync) {
if (workEventsBySourceId.hasOwnProperty(eventToSync.getId())) {
const correspondingWorkEvent = workEventsBySourceId[eventToSync.getId()];
delete workEventsBySourceId[eventToSync.getId()]
if (correspondingWorkEvent.getStartTime() === eventToSync.getStartTime() &&
correspondingWorkEvent.getEndTime() === eventToSync.getEndTime()) {
continue;
}
correspondingWorkEvent.setTime(eventToSync.getStartTime(), eventToSync.getEndTime());
eventsChanged += 1;
} else {
const newEvent = workCalendar.createEvent('busy', eventToSync.getStartTime(), eventToSync.getEndTime());
newEvent.setTag('source', 'personal-calendar-sync');
newEvent.setTag('source_id', eventToSync.getId());
eventsAdded += 1;
}
}
const remainingEventsToDelete = Object.values(workEventsBySourceId);
remainingEventsToDelete.forEach(remainingEventToDelete => {
// Switch to this line for testing to prevent deleting events
// remainingEventToDelete.setColor(CalendarApp.EventColor.RED);
remainingEventToDelete.deleteEvent();
eventsDeleted += 1
});
console.log(`${eventsAdded} events added, ${eventsChanged} events changed, ${eventsDeleted} deleted.`)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment