![見出し画像](https://assets.st-note.com/production/uploads/images/147134471/rectangle_large_type_2_4d7d37c032b2098f2cd584d4708da12a.png?width=1200)
[コード公開] GAS & Zapierで、自分の作業可能時間を可視化してみる
note AI creativeの田中です。
自分のGoogleカレンダーから作業可能時間を計算して、Slackに通知する仕組みを作ってみたので、作り方を解説してみます。
![](https://assets.st-note.com/img/1720849044828-vdRG9HxAZa.png?width=1200)
仕組み
作業可能時間の計算:GAS(Google App Script)を使って、自分のGoogleカレンダーで予定が入っていない時間を計算して、スプレッドシートに出力。
Slack通知:Zapierでスプレッドシートを読みこみ、結果をSlackにポストする。
1. 作業可能時間の計算
GASスクリプトは以下。
自分のGoogleカレンダーを読み込んで、直近7日間のうち予定の入っていない時間を計算する(土日は除く)
結果を「シート1」の「A2」「B2」に出力する(実際使うのはB2)
最新の結果は、常に「B2」に入るようにしている。これにより、後のZapierの処理がシンプルになる。
![](https://assets.st-note.com/img/1720849711806-OOYfSbcTn5.png?width=1200)
function getWorkingHours() {
var calendar = CalendarApp.getCalendarById('primary');
var myEmail = Session.getActiveUser().getEmail();
var today = new Date();
var workDays = 0;
var dates = [];
var workingHours = [];
var totalWorkHours = 0;
while (workDays < 7) {
var specificDay = new Date(today);
specificDay.setDate(today.getDate() + workDays);
specificDay.setHours(0, 0, 0, 0); // 日付の開始時間
var dayOfWeek = specificDay.getDay();
// 土日を除外
if (dayOfWeek === 0 || dayOfWeek === 6) {
workDays++;
continue;
}
var endOfDay = new Date(specificDay);
endOfDay.setHours(23, 59, 59, 999); // 日付の終了時間
// その日のイベントを取得
var events = calendar.getEvents(specificDay, endOfDay);
// 9:30と18:30の時間帯を設定
var workStartTime = new Date(specificDay);
workStartTime.setHours(9, 30, 0, 0);
var workEndTime = new Date(specificDay);
workEndTime.setHours(18, 30, 0, 0);
var dayWorkHours = (workEndTime - workStartTime) / (1000 * 60 * 60); // 稼働時間を時間単位で計算
var totalBusyMinutes = 0;
for (var i = 0; i < events.length; i++) {
var event = events[i];
var attendees = event.getGuestList();
var isAttending = false;
// 自分がイベントのホストまたは参加者であるかを確認
if (event.getCreators().indexOf(myEmail) !== -1 || event.getMyStatus() == CalendarApp.GuestStatus.YES) {
isAttending = true;
} else {
for (var j = 0; j < attendees.length; j++) {
var attendee = attendees[j];
if (attendee.getEmail() == myEmail && attendee.getGuestStatus() == CalendarApp.GuestStatus.YES) {
isAttending = true;
break;
}
}
}
if (isAttending) {
var startTime = event.getStartTime();
var endTime = event.getEndTime();
// イベントの開始時刻と終了時刻が9:30 - 18:30内にあるかを確認
if (startTime >= workStartTime && endTime <= workEndTime) {
var duration = (endTime - startTime) / (1000 * 60); // ミリ秒を分に変換
totalBusyMinutes += duration;
}
}
}
var totalBusyHours = totalBusyMinutes / 60;
var remainingWorkHours = dayWorkHours - totalBusyHours;
totalWorkHours += remainingWorkHours;
// 日付のフォーマットを yyyy/MM/dd (曜日) のようにする
var daysOfWeek = ['日', '月', '火', '水', '木', '金', '土'];
var formattedDate = Utilities.formatDate(specificDay, Session.getScriptTimeZone(), 'yyyy/MM/dd') + ' (' + daysOfWeek[specificDay.getDay()] + ')';
// 日付と稼働時間の残りを配列に保存
dates.push(formattedDate);
workingHours.push(formattedDate + ':' + remainingWorkHours.toFixed(1) + '時間');
workDays++;
}
// 合計時間を追加
workingHours.push('---');
workingHours.push('合計:' + totalWorkHours.toFixed(1) + '時間');
// スプレッドシートとシートを指定
var spreadsheetId = '<ここにシートIDを記載>';
var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName('シート1');
// ヘッダーを設定
sheet.getRange('A1').setValue('date');
sheet.getRange('B1').setValue('working_hours');
// A2とB2に既存データがある場合、その行を下にずらす
var rangeA2 = sheet.getRange('A2');
var rangeB2 = sheet.getRange('B2');
if (rangeA2.getValue() || rangeB2.getValue()) {
sheet.insertRowsBefore(2, 1); // 2行目に新しい行を挿入
}
// 配列の内容をスプレッドシートのA2とB2に書き出し
sheet.getRange('A2').setValue(dates.join('\n'));
sheet.getRange('B2').setValue(workingHours.join('\n'));
}
毎週土曜日にこの処理は動くようにしている。
![](https://assets.st-note.com/img/1720849773683-hyML6pELuL.png?width=1200)
2. Slack通知(Zapier)
以下が全体像。
![](https://assets.st-note.com/img/1720849883546-cU5AgDhIsR.png?width=1200)
ステップ2のアクション内容は以下。
![](https://assets.st-note.com/img/1720850025297-0zUdKbTltz.png?width=1200)
ステップ3のアクション内容は以下。
![](https://assets.st-note.com/img/1720850160357-EWSeVjS0Pf.png?width=1200)
<@SlackメンバーID> とすることで、メンションが可能。
以下のような通知が毎週月曜日、自分のタイムラインチャンネルに流れるようになっている。
![](https://assets.st-note.com/img/1720849044828-vdRG9HxAZa.png?width=1200)
▼noteの技術記事が読みたい方はこちら
この記事が気に入ったらサポートをしてみませんか?