土日、祝日用カレンダー、独自の休業日カレンダーを調べ、処理を実行してよい日かを判定します。
カレンダーを取得できない場合は停止し、予定がない平日として続行しません。
練習コード・入力JSON・文字変換ブックをダウンロード(ZIP)できます。
記事ごとに別のApps Scriptプロジェクトを使い、新規の練習データを対象にしてください。
最終確認は2026年10月2日です。
GASの51項目はローカルの模擬検証、curlの3項目はローカルHTTP環境、数式の8項目はArtifact Toolでの検証です。
Googleへの認可・実シートの操作・カレンダーの列挙・配備後のHTTP通信・Google Sheetsでの数式計算は未検証です。
練習用カレンダーと日本時間の設定
最初は練習用カレンダーを2つ作り、他の人を招待せずに使います。
休日用には2026年10月5日、独自休業日用には2026年10月6日の終日予定を入れます。
これらは検証用の架空の休業日で、日本の祝日を示す日付ではありません。
| 設定 | 内容 |
|---|---|
| HOLIDAY_CALENDAR_ID | 練習用の休日カレンダーID。必須 |
| SKIP_CALENDAR_ID | 独自休業日の練習カレンダーID。使わない場合は未設定 |
| プロジェクトのタイムゾーン | Asia/Tokyo |
| 両カレンダーのタイムゾーン | Asia/Tokyo |
カレンダー設定の「カレンダーの統合」にあるIDを、Apps Scriptのスクリプトプロパティへ入れます。
プロジェクトと各カレンダーのタイムゾーンが異なる場合、この日本時間用の例は停止します。
カレンダーの共有範囲を広げる処理はありません。
読み取りだけで休日判定を実行する
次のコードを保存し、demoHolidayCheckを実行します。
これは2026年10月5日の判定です。
現在の日時で確認する場合はpreviewTodayを実行します。
カレンダーの予定を読む権限を確認して認可します。
const PRACTICE_ZONE = 'Asia/Tokyo';
function dateParts_(date) {
if (!(date instanceof Date) || !Number.isFinite(date.getTime())) throw new Error('有効な日時を指定してください');
const key = Utilities.formatDate(date, PRACTICE_ZONE, 'yyyy-MM-dd');
const day = new Date(key + 'T00:00:00Z').getUTCDay();
return {key: key, weekend: day === 0 || day === 6};
}
function configuredCalendar_(key, optional) {
const id = PropertiesService.getScriptProperties().getProperty(key);
if (!id) {
if (optional) return null;
throw new Error(key + 'を設定してください');
}
const calendar = CalendarApp.getCalendarById(id);
if (!calendar) throw new Error(key + 'のカレンダーを取得できません');
if (calendar.getTimeZone() !== PRACTICE_ZONE) throw new Error(key + 'のタイムゾーンをAsia/Tokyoにそろえてください');
return calendar;
}
function allDayBlocks_(events, key) {
return events.some(event => {
if (!event.isAllDayEvent()) return false;
const start = Utilities.formatDate(event.getAllDayStartDate(), PRACTICE_ZONE, 'yyyy-MM-dd');
const end = Utilities.formatDate(event.getAllDayEndDate(), PRACTICE_ZONE, 'yyyy-MM-dd');
return start <= key && key < end;
});
}
function shouldRunAt_(date) {
if (Session.getScriptTimeZone() !== PRACTICE_ZONE) throw new Error('プロジェクトのタイムゾーンをAsia/Tokyoにそろえてください');
const day = dateParts_(date);
// 設定が壊れていたら、平日扱いで続行せず停止します。
const holidays = configuredCalendar_('HOLIDAY_CALENDAR_ID', false);
const custom = configuredCalendar_('SKIP_CALENDAR_ID', true);
const noon = Utilities.parseDate(day.key + ' 12:00', PRACTICE_ZONE, 'yyyy-MM-dd HH:mm');
const holiday = allDayBlocks_(holidays.getEventsForDay(noon), day.key);
const customSkip = custom ? allDayBlocks_(custom.getEventsForDay(noon), day.key) : false;
return {date: day.key, weekend: day.weekend, holiday: holiday, customSkip: customSkip,
shouldRun: !day.weekend && !holiday && !customSkip};
}
function previewToday() {
const result = shouldRunAt_(new Date());
console.log(JSON.stringify(result));
return result;
}
function demoHolidayCheck() {
const result = shouldRunAt_(new Date('2026-10-05T12:00:00+09:00'));
console.log(JSON.stringify(result));
return result;
}
結果のshouldRunがtrueなら、設定した条件では実行日です。
この例は結果をログへ出すだけで、メールやチャットを送信しません。
トリガーや予定の作成・変更も行いません。
確認結果と切り分け
| 条件 | 結果 |
|---|---|
| 10月5日の終日予定が休日用にある | holiday:true、shouldRun:false |
| 10月6日の終日予定が独自休業日にある | customSkip:true、shouldRun:false |
| 土日 | weekend:true、shouldRun:false |
| 平日で終日予定がない | shouldRun:true |
| 時刻付きの会議がある | この例の休業日条件には含めない |
| 複数日の終日予定 | 開始日以上、終了日未満の各日を除外 |
| ID違い・アクセス不可・タイムゾーン違い | エラーで停止。平日扱いで続行しない |
| 独自休日IDだけ未設定 | 休日用カレンダーと土日で判定する |
getAllDayEndDateが返す日は、終日予定が終わった翌日の先頭です。
そのため終了日そのものは休業日から除きます。
UTCでは前日でも日本時間では翌日になる境界を含め、模擬検証で日付と曜日を確認しました。
日本の祝日カレンダーに替える場合
練習後に購読している日本の祝日カレンダーを使う場合は、そのID・予定・タイムゾーンを確認して指定します。
Googleカレンダーには祝日以外の行事も含まれることがあります。
このコードは指定カレンダーの終日予定を除外日として扱うため、実際の予定が業務上の休業日と合うか確認してください。
画面上の表示設定だけでAPIの取得結果も同じ範囲になるとは仮定しません。
停止と戻し方
この読み取り例はデータを変更しません。
既存の定期処理に組み込む場合は、結果と除外日の一覧を先に確認し、停止時はそのトリガーを止めます。
練習カレンダーの予定やIDを業務用へ切り替える前に、元の設定を手元へ控えます。
公式資料
日ごとの予定取得とタイムゾーン、終日予定の終了日、祝日とその他の行事の表示を参照してください。
関連記事・旧実装の参考資料
旧GitHubコードや外部の参考例は、現在の記事のZIPと異なる場合があります。
今回の練習は本文のセル番地・プロパティ・ZIPをそろえて実行してください。




