見出し画像

[コード公開] GAS & Zapierで、自分の作業可能時間を可視化してみる

note AI creativeの田中です。

自分のGoogleカレンダーから作業可能時間を計算して、Slackに通知する仕組みを作ってみたので、作り方を解説してみます。

7/8週の作業時間

仕組み

  1. 作業可能時間の計算:GAS(Google App Script)を使って、自分のGoogleカレンダーで予定が入っていない時間を計算して、スプレッドシートに出力。

  2. Slack通知:Zapierでスプレッドシートを読みこみ、結果をSlackにポストする。

1. 作業可能時間の計算

GASスクリプトは以下。

  • 自分のGoogleカレンダーを読み込んで、直近7日間のうち予定の入っていない時間を計算する(土日は除く)

  • 結果を「シート1」の「A2」「B2」に出力する(実際使うのはB2)

    • 最新の結果は、常に「B2」に入るようにしている。これにより、後のZapierの処理がシンプルになる。

スプレッドシートの出力
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'));
}

毎週土曜日にこの処理は動くようにしている。

トリガー

2. Slack通知(Zapier)

以下が全体像。

Zapierの処理全体像

ステップ2のアクション内容は以下。

ステップ2のアクション内容

ステップ3のアクション内容は以下。

Slack投稿アクション

<@SlackメンバーID> とすることで、メンションが可能。
以下のような通知が毎週月曜日、自分のタイムラインチャンネルに流れるようになっている。

7/8週の作業時間


▼noteの技術記事が読みたい方はこちら


この記事が気に入ったらサポートをしてみませんか?