毎週の予定を1回だけ確認したいときと、繰り返しの設定全体を扱うときでは、対象が違います。GASのCalendarEventは予定の1回を扱う入口で、CalendarEventSeriesは繰り返し全体を扱います。更新する前に、今どちらを取得しているかを確かめます。
特にgetEventSeries()が返ったからといって、その予定が繰り返しだとは限りません。公式資料では、繰り返しでない予定にもSeriesオブジェクトが返ると説明されています。繰り返しかどうかはisRecurringEventで判定します。
最初は予定の一覧を読むだけにする
練習用カレンダーへ、毎週の架空の打ち合わせを画面から作ります。実在の出席者やゲストは追加しません。1回の変更を試す前に、取得した予定の日時と、繰り返しの判定をログへ出して比べます。
以下の例は固定した期間の予定を読み取るだけです。予定名や説明文もログへ出さず、日時とiCalUID、繰り返し判定を返します。期間は日本時間の11月1日0時から8日0時までとして、時差を文字列へ明示しています。
繰り返し判定と日時を並べるコード
isRecurringEventがtrueのときだけ、対応するSeriesのIDも読みます。更新や削除のメソッドは呼びません。
function describeOccurrence(event) {
const recurring = event.isRecurringEvent();
return {
iCalUID: event.getId(),
recurring: recurring,
start: event.getStartTime().toISOString(),
end: event.getEndTime().toISOString(),
seriesUID: recurring ? event.getEventSeries().getId() : null
};
}
function readPracticeOccurrences(calendar, start, end) {
return calendar.getEvents(start, end).map(describeOccurrence);
}
function previewOccurrenceTargets() {
const calendar = CalendarApp.getCalendarById('練習用カレンダーID');
if (!calendar) throw new Error('カレンダーがありません');
const rows = readPracticeOccurrences(calendar,
new Date('2026-11-01T00:00:00+09:00'),
new Date('2026-11-08T00:00:00+09:00'));
console.log(JSON.stringify(rows));
}
毎週の予定から取得した回はrecurring:true、単発予定はfalseになる想定です。単発予定のseriesUIDはこの例ではnullにします。日時はISO形式のUTC表示なので、画面の日本時間と比較するときは時差も考慮します。
同じiCalUIDでも開催日は別
繰り返し予定の各回はCalendarAppでは同じiCalUIDを共有します。IDだけを保存して「11月2日の回」を特定したつもりになると、どの回を扱ったかが残りません。対象の開始日時も確認します。
公式のCalendarEventとCalendarEventSeriesは、対象の範囲を分けて説明しています。各回を扱うオブジェクトからSeriesを取得した後は、全体へ影響する処理を呼ぶ可能性があることに注意してください。
1回だけを別の時刻へ変える場合と、毎週の時刻をまとめて変える場合では、変更結果の確認範囲も違います。後者を試すときは、対象日だけでなく次の回や例外設定も確認する必要があります。
例外となった回を見落とさない
ある回だけ時間や場所を変えた予定は、通常の繰り返し条件だけを見ても分かりません。シリーズ全体の設定を新しくした際に、その例外をどう扱うかまで確認します。変更前の画面と予定情報を控え、練習用で結果を見てから進めます。
同じタイトルで毎週作った単発予定は、見た目が似ていても繰り返しのSeriesとは別です。タイトルが同じだから1つのシリーズとして一括処理する、といった推測はしないでください。
ローカルでは代用イベントで繰り返しと単発を分け、単発でgetEventSeriesを呼ばないことと、日時の受け渡しを確認しました。Google上の繰り返し編集や例外設定は未実行です。予定登録の基本と実行履歴の確認を基に、読み取りで対象を確かめてから変更へ進みます。
