動機
複数の団体に所属してると、スケジュールの同期に四苦八苦することになります。ダブルブッキングにならないよう、既に予定が埋まってることを示す "用事あり" を、双方のカレンダーに登録する作業がとても大変でした。A 社の予定を B 社のカレンダーにコピーし、B 社の予定を A 社にコピーし…。
そんな中、 GAS (Google Apps Script) を使うというアイデアをもらったので、作ってみました。Google Calendar 同士であれば、これでカレンダーの同期作業が大幅に軽減されると思います。
想定運用
各所属のメインとなるカレンダーとは別に、同期用のカレンダーを作成します。
メインとなるカレンダーは、その所属先の予定と、既にブッキングされていることを表明するための "用事あり" を入れます。
同期用のカレンダーは、メインカレンダーから "用事あり" を除外した予定をコピーします。このカレンダーを、もう片方の所属先の同期に使います。
GAS コード
想定運用 の二つのカレンダーの同期を取ります。次のコードは、メインとなるカレンダーから、同期用カレンダーに予定をコピーするコードです。
ご自身の GAS 環境に入れる場合は、以下のコードの中に二つのカレンダーの ID を設定することと、トリガーを設定することが必要になります。
const sourceCalendarID = '' // メインとなるカレンダーの ID
const targetCalendarID = '' // 同期用カレンダーの ID
/**
* 一週間分のイベントを同期する
* カレンダーの変更をトリガーにする想定
*/
function updateOneWeek() {
const fromDateTime = new Date()
const toDateTime = new Date()
toDateTime.setDate(fromDateTime.getDate() + 7)
libUpdateCalendar(fromDateTime, toDateTime)
}
/**
* 三ヶ月分のイベントを同期する
* 一日に一度、夜中に起動する、ぐらいの想定
*/
function updateThreeMonths() {
const fromDateTime = new Date()
const toDateTime = new Date()
toDateTime.setDate(fromDateTime.getDate() + 90)
libUpdateCalendar(fromDateTime, toDateTime)
}
/**
* 指定範囲のカレンダーを同期する
* (Utility)
*/
const libUpdateCalendar = (fromDateTime, toDateTime) => {
// ターゲットカレンダーから、指定期間のイベントを削除
const targetCalendar = CalendarApp.getCalendarById(targetCalendarID)
const targetEvents = targetCalendar.getEvents(fromDateTime, toDateTime)
targetEvents.forEach(it => it.deleteEvent())
// 指定期間のイベントをソースカレンダーからターゲットカレンダーへ複製
const sourceCalendar = CalendarApp.getCalendarById(sourceCalendarID)
const sourceEvents = sourceCalendar.getEvents(fromDateTime, toDateTime)
sourceEvents.forEach(it => {
if (it.getTitle() === '用事あり') return
if (it.getMyStatus() === CalendarApp.GuestStatus.NO) return
if (it.isAllDayEvent()) return
targetCalendar.createEvent(it.getTitle(), it.getStartTime(), it.getEndTime())
})
}
こちらは、自動的に "用事あり" を作るコードです。
const mainCalendarID = '' // メインとなるカレンダーの ID
const otherCalendarIDs = [''] // ブロックするイベントのあるカレンダーの ID (複数可)
/**
* 一週間分のイベントを同期する
* 一時間ごとぐらいの想定
*/
function updateOneWeek() {
const fromDateTime = new Date()
const toDateTime = new Date()
toDateTime.setDate(fromDateTime.getDate() + 7)
libUpdateCalendar(fromDateTime, toDateTime)
}
/**
* 三ヶ月分のイベントを同期する
* 一日に一度、夜中に起動する、ぐらいの想定
*/
function updateThreeMonthes() {
const fromDateTime = new Date()
const toDateTime = new Date()
toDateTime.setDate(fromDateTime.getDate() + 90)
libUpdateCalendar(fromDateTime, toDateTime)
}
/**
* 指定範囲のカレンダーを同期する
* (Utility)
*/
const libUpdateCalendar = (fromDateTime, toDateTime) => {
// メインカレンダーから、指定期間のブロックイベントを削除
const mainCalendar = CalendarApp.getCalendarById(mainCalendarID)
const targetEvents = mainCalendar.getEvents(fromDateTime, toDateTime)
targetEvents.forEach(it => {
if (it.getTitle() !== '用事あり') return
it.deleteEvent()
})
// 指定期間のイベントについて、メインカレンダーにブロックイベントを作成
const blocks = otherCalendarIDs.map(it =>
CalendarApp.getCalendarById(it).getEvents(fromDateTime, toDateTime)
)
blocks.flat().forEach(it =>
mainCalendar.createEvent('用事あり', it.getStartTime(), it.getEndTime())
)
}