Last active
January 30, 2026 08:38
-
-
Save adrianlungu/9c69e75bba6c1363dc26c5e27968c5b2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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