1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

複数所属のカレンダー同期に疲れた人へ

Last updated at Posted at 2023-10-04

動機

複数の団体に所属してると、スケジュールの同期に四苦八苦することになります。ダブルブッキングにならないよう、既に予定が埋まってることを示す "用事あり" を、双方のカレンダーに登録する作業がとても大変でした。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())
  )
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?