みなさんこんにちは!GASおじさんです。
今回はGoogleカレンダーから空き時間を取得するスクリプトをご紹介します。
Youtubeでも解説していますので動画で見たい人は以下からどうぞ。
Googleカレンダーから空き時間を取得するスクリプト
スクリプトの実装
まずは以下3つのスクリプトをコピペしてください。
①グローバル変数
const CALENDAR_ID = 'example@gmail.com'; // カレンダーIDを指定
const AT_LEAST_MINUTES = 60; // 少なくとも確保したい時間を「分」で指定
const WORKTIME = {
START: {
HOURS: 9, MINUTES: 30, // 勤務開始時間の「時」「分」を指定
},
END: {
HOURS: 18, MINUTES: 0, // 勤務終了時間の「時」「分」を指定
}
};
const DAYS = ['日', '月', '火', '水', '木', '金', '土'];
CALENDAR_ID
で空き時間を抽出したいカレンダーのIDを指定してください。AT_LEAST_MINUTES
で少なくとも確保したい時間を「分」で指定してください。上記は少なくとも空き時間が60分以上ある場合に空き時間として抽出するサンプルです。WORKTIME
の各数値を指定してください。上記は9:30勤務開始、18:00勤務終了の場合のサンプルです。
②getFreeTimeList関数
/**
* 特定の日付の空き時間を配列で取得する関数
* @param {Date} date - 日付
* @returns {Object[]} - 空き時間オブジェクトの配列
*/
function getFreeTimeList(date=new Date()) {
const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
const worktime = {
start: new Date(
date.getFullYear(), date.getMonth(), date.getDate(),
WORKTIME.START.HOURS, WORKTIME.START.MINUTES
),
end: new Date(
date.getFullYear(), date.getMonth(), date.getDate(),
WORKTIME.END.HOURS, WORKTIME.END.MINUTES
),
};
const events = calendar.getEvents(worktime.start, worktime.end).filter(e => {
const hours = (e.getEndTime() - e.getStartTime())/1000/60/60;
return hours < 24; // 終日イベントを除外
});
// 重複イベントを結合した仮想イベントを作成
const virtualEvents = createVirtualEvents(calendar, events);
let freeTimeList = [];
if(virtualEvents.length == 0){
const freeTime = {start: worktime.start, end: worktime.end};
freeTimeList.push(freeTime);
}
if(virtualEvents.length == 1){
const event = virtualEvents[0];
const freeTime1 = {start: worktime.start, end: event.start};
const freeTime2 = {start: event.end, end: worktime.end};
freeTimeList.push(freeTime1, freeTime2);
}
if(virtualEvents.length >= 2){
for(let i = 0; i < virtualEvents.length; i++){
const event = virtualEvents[i];
if(i == 0){
// 勤務開始時間から最初のイベントまでの空き時間を追加
const freeTime = {start: worktime.start, end: event.start};
freeTimeList.push(freeTime);
}else{
// イベントとイベントの間の空き時間を追加
const prevEvent = virtualEvents[i-1];
const freeTime = {start: prevEvent.end, end: event.start};
freeTimeList.push(freeTime);
}
if(i == virtualEvents.length-1){
// 最後のイベントから勤務終了時間までの空き時間を追加
const freeTime = {start: event.end, end: worktime.end};
freeTimeList.push(freeTime);
}
}
}
// 指定の時間(分)より少ないものを除外する
freeTimeList = freeTimeList.filter(freeTime => {
const minutes = (freeTime.end - freeTime.start)/1000/60;
return minutes >= AT_LEAST_MINUTES;
});
return freeTimeList;
}
③createVirtualEvents関数
/**
* 終日イベントを除外し、重複イベントを結合した仮想イベントを作成する関数
* @param {CalendarApp.Calendar} calendar - カレンダーオブジェクト
* @param {Date[]} events - イベントオブジェクトの配列
* @returns {Object[]} 仮想イベントの配列
*/
function createVirtualEvents(calendar, events) {
const virtualEvents = [];
for(const event of events){
// 重複イベントがあるかどうかを確認
const eventsInEvent = calendar.getEvents(event.getStartTime(), event.getEndTime()).filter(e => {
const hours = (e.getEndTime() - e.getStartTime())/1000/60/60;
return hours < 24; // 終日イベントを除外
});
if(eventsInEvent.length == 1){
// 重複イベントがない場合は、そのまま追加
const virtualEvent = {start: event.getStartTime(), end: event.getEndTime()};
virtualEvents.push(virtualEvent);
}else{
// 重複イベントがある場合は、開始時間の最小値と終了時間の最大値を計算して1個の仮想イベントを作成
const firstEvent = eventsInEvent.reduce((a, b) => a.getStartTime() < b.getStartTime() ? a : b);
const lastEvent = eventsInEvent.reduce((a, b) => a.getEndTime() > b.getEndTime() ? a : b);
const virtualEvent = {start: firstEvent.getStartTime(), end: lastEvent.getEndTime()};
// 生成する配列をユニークにする
const jsonEvents = JSON.stringify(virtualEvents);
const jsonEvent = JSON.stringify(virtualEvent);
if(!jsonEvents.includes(jsonEvent)) virtualEvents.push(virtualEvent);
}
}
return virtualEvents;
}
スクリプトの検証
上記3つのスクリプトをコピペしたら、Googleカレンダーに適当な予定を入れて、getFreeTimeList関数の動きを検証してみましょう。
Googleカレンダーは以下のような状態です。
11月1日の12:00〜14:00に予定を入れました。
この状態で以下のmyFunction関数を定義し実行してみます。その際、getFreeTimeList関数の引数に11月1日を指定しています。
function myFunction() {
const date = new Date(2024, 10, 1); // 特定の日付を指定
const freeTimeList = getFreeTimeList(date);
console.log(freeTimeList);
}
実行結果は以下のようになりました。
無事、
- 2024年11月1日 9:30〜12:00
- 2024年11月1日 14:00〜18:00
という、2つの空き時間を抽出してくれました。
使用例1: スプレッドシートに入力
今日の日付から向こう7日分の空き時間を抽出して、スプレッドシートに入力します。
スプレッドシートを起動し、コンテナバインドスクリプトに以下のコードをコピペして実行します(シート名は必要に応じて書き換えてください)。
function setFreeTimeToSheet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
for(let i = 0; i < 7; i++){
const date = new Date(y, m, d+i);
const freeTimeList = getFreeTimeList(date);
let text = '';
for(const freeTime of freeTimeList){
const start = Utilities.formatDate(freeTime.start, 'Asia/Tokyo', 'H:mm');
const end = Utilities.formatDate(freeTime.end, 'Asia/Tokyo', 'H:mm');
text += `${start}〜${end}, `;
}
text = text.slice(0, -2); // 末尾のカンマを削除
sheet.appendRow([date, text])
}
}
実行結果は以下のとおりです。
使用例2: Gmailの下書きを作成
続けて、今日の日付から向こう7日分の空き時間を抽出して、Gmailの下書きを作成するスクリプトです。
function createDraft() {
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
let text = '';
for(let i = 0; i < 7; i++){
const date = new Date(y, m, d+i);
const formatDate = Utilities.formatDate(date, 'Asia/Tokyo', `M月d日(${DAYS[date.getDay()]})`);
text += `${formatDate} `;
const freeTimeList = getFreeTimeList(date);
if (freeTimeList.length == 0) text += '- ';
for(const freeTime of freeTimeList){
const start = Utilities.formatDate(freeTime.start, 'Asia/Tokyo', 'H:mm');
const end = Utilities.formatDate(freeTime.end, 'Asia/Tokyo', 'H:mm');
text += `${start}〜${end}, `;
}
text = text.slice(0, -2); // 末尾のカンマを削除
text += '\n';
}
const recipient = 'example@gmail.com';
const subject = '空き時間';
let body = `以下の時間でご都合いかがでしょうか?\n\n`;
body += text;
body += '\nご確認の程、よろしくお願いいたします。';
GmailApp.createDraft(recipient, subject, body);
}
実行結果は以下のとおりです。
まとめ
以上、Googleカレンダーから空き時間を取得するスクリプトでした。
グローバル変数の値や取得する日数については、実際の環境に応じてカスタマイズしながらご利用ください。
コメント