Skip to content

Instantly share code, notes, and snippets.

@adrianlungu
Last active January 30, 2026 08:38
Show Gist options
  • Select an option

  • Save adrianlungu/9c69e75bba6c1363dc26c5e27968c5b2 to your computer and use it in GitHub Desktop.

Select an option

Save adrianlungu/9c69e75bba6c1363dc26c5e27968c5b2 to your computer and use it in GitHub Desktop.
// Google Script usable to setup and run via a trigger on https://script.google.com/
//
// Main goal is to sync personal events from the personal calendar as busy events
// in the work calendar.
function syncPersonalToTeam() {
const personalId = 'personal@gmail.com';
const workId = 'work@gmail.com';
const teamId = 'team_id@group.calendar.google.com';
const now = new Date();
const future = new Date();
future.setDate(now.getDate() + 30);
const personal = CalendarApp.getCalendarById(personalId);
const work = CalendarApp.getCalendarById(workId);
const team = CalendarApp.getCalendarById(teamId);
const eventTitle = "Adrian Lungu Busy"
const eventDayTitle = "Adrian Lungu Day Off"
const allowedAllDayTypes = [
CalendarApp.EventType.OUT_OF_OFFICE,
CalendarApp.EventType.DEFAULT,
CalendarApp.EventType.FOCUS_TIME,
];
// Sync personal events completely
const events = personal.getEvents(now, future);
events.forEach(event => {
const existing = team.getEvents(event.getStartTime(), event.getEndTime(), { search: eventTitle });
if (existing.length === 0) {
Logger.log('%s: %s - %s; %s; %s', event.getTitle(), event.getStartTime(), event.getEndTime(), event.isAllDayEvent(), event.getEventType());
team.createEvent(eventTitle, event.getStartTime(), event.getEndTime());
}
});
// Sync only full day work events
const eventsWork = work.getEvents(now, future);
eventsWork.forEach(event => {
// Skip non-matching types like WORKING_LOCATION, BIRTHDAY etc; and also
if (!allowedAllDayTypes.includes(event.getEventType())) return;
// Check if it's an all day event
if (!isVisuallyAllDay(event)) return;
Logger.log('%s: %s - %s; %s; %s', event.getTitle(), event.getStartTime(), event.getEndTime(), event.isAllDayEvent(), event.getEventType());
const workEventTitle = event.getTitle();
var startDate = new Date()
var endDate = new Date()
if (event.isAllDayEvent()) {
startDate = event.getAllDayStartDate();
endDate = event.getAllDayEndDate();
} else {
startDate = event.getStartTime();
endDate = event.getEndTime();
}
const existing = team.getEventsForDay(startDate).find(e =>
e.isAllDayEvent() &&
e.getTitle() === eventDayTitle &&
e.getAllDayStartDate().getTime() === startDate.getTime() &&
e.getAllDayEndDate().getTime() === endDate.getTime()
);
if (!existing) {
team.createAllDayEvent(eventDayTitle, startDate, endDate, {
description: event.getDescription(),
location: event.getLocation()
});
}
});
}
function isVisuallyAllDay(event) {
if (event.isAllDayEvent()) return true;
const start = event.getStartTime();
const end = event.getEndTime();
// Check: starts at midnight, ends at midnight + whole-day multiple
const isAlignedToMidnight =
start.getHours() === 0 && start.getMinutes() === 0 &&
end.getHours() === 0 && end.getMinutes() === 0;
const duration = end - start; // in ms
const isWholeDay = duration % (24 * 60 * 60 * 1000) === 0;
return isAlignedToMidnight && isWholeDay;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment