🐣

Googleカレンダーの翌週の休暇予定をSlackに通知する

2023/05/07に公開

背景・概要

有休をその当日に通知させるGASを作った後に、毎週金曜日に翌週の有休を通知させるGASも欲しくなりました。
急な有休までは把握できませんが、あらかじめ休日の予定を知っていると、予定が立てやすくなります。

Slack通知サンプル

■来週の有休をお知らせします
2023/05/09 (火):
【カレンダー1】【全休】全休:山田
2023/05/11 (木):
【カレンダー2】【午前休】午前休:鈴木
2023/05/10 (水):
【カレンダー2】【全休】全休:田中
【カレンダー3】【午後休】午後休:鈴木

GAS

  • トリガーを毎日特定の時間に動くように設定してください。土日祝はスキップする設定になっています。
    • 金曜日に通知されますが、金曜日が祝日の場合は木曜日に通知されます。
  • カレンダーIDとSlackのWebhook URLを定数に設定してください。
    • 複数のGoogleカレンダーを設定できます。
function postNextWeekHolidaySchedule() {
  const today = new Date();
  const dayOfWeek = today.getDay();

  // 金曜日であれば通知を行う
  if (dayOfWeek === 5 && isBusinessDay()) {
    sendNextWeekHolidayNotifications();
  }
  // 木曜日であれば、明日(金曜日)が祝日かどうかをチェックし、祝日であれば通知を行う
  else if (dayOfWeek === 4) {
    const tomorrow = new Date(today);
    tomorrow.setDate(today.getDate() + 1);
    if (!isBusinessDay(tomorrow)) {
      sendNextWeekHolidayNotifications();
    }
  }
}

function sendNextWeekHolidayNotifications() {
  const calendarIds = [
    "calendarId1を入れる",
    "calendarId2を入れる",
    "calendarId3を入れる"
  ]; // Add more calendar IDs here.
  const slackWebhookUrl = "slackWebhookUrlを入れる";

  let holidaysByDate = {};

  for (const calendarId of calendarIds) {
    const calendar = CalendarApp.getCalendarById(calendarId);
    const today = new Date();
    const startDate = new Date(today);
    startDate.setDate(today.getDate() + 2); // Start from next Monday
    const endDate = new Date(startDate);
    endDate.setDate(startDate.getDate() + 6); // End on next Sunday

    const events = calendar.getEvents(startDate, endDate);

    for (let i = 0; i < events.length; i++) {
      const title = events[i].getTitle();
      const eventDate = events[i].getStartTime();
      const dateString = Utilities.formatDate(
        eventDate,
        Session.getScriptTimeZone(),
        "yyyy/MM/dd"
      );

      if (!holidaysByDate[dateString]) {
        holidaysByDate[dateString] = {
          dayOfWeek: getDayOfWeekString(eventDate.getDay()),
          holidays: [],
        };
      }

      holidaysByDate[dateString].holidays.push({
        calendarName: calendar.getName(),
        title: title,
      });
    }
  }

  const slackPayload = {
    text: "■来週の休日をお知らせします\n",
    link_names: 1,
  };

  for (const date in holidaysByDate) {
    slackPayload.text += `\n${date} (${holidaysByDate[date].dayOfWeek}):\n`;

    for (const holiday of holidaysByDate[date].holidays) {
      if (holiday.title.includes("全休")) {
        slackPayload.text += `【${holiday.calendarName}】【全休】${holiday.title}\n`;
      } else if (holiday.title.includes("午前休")) {
        slackPayload.text += `【${holiday.calendarName}】【午前休】${holiday.title}\n`;
      } else if (holiday.title.includes("午後休")) {
        slackPayload.text += `【${holiday.calendarName}】【午後休】${holiday.title}\n`;
      }
    }
  }

  if (slackPayload.text === "■来週の有休をお知らせします\n") {
    return;
  }

  const options = {
    method: "post",
    contentType: "application/json",
    payload: JSON.stringify(slackPayload),
  };
  UrlFetchApp.fetch(slackWebhookUrl, options);
}


function isBusinessDay(date = new Date()) {
  const dayOfWeek = date.getDay();

  // 土日は営業日ではない
  if (dayOfWeek === 0 || dayOfWeek === 6) {
    return false;
  }

  // 祝日は営業日ではない
  const calendar = CalendarApp.getCalendarById(
    "ja.japanese#holiday@group.v.calendar.google.com"
  );
  const holidays = calendar.getEventsForDay(date);
  if (holidays.length > 0) {
    return false;
  }

  // 営業日の場合はtrueを返す
  return true;
}

function getDayOfWeekString(dayOfWeek) {
  const days = [
    "日",
    "月",
    "火",
    "水",
    "木",
    "金",
    "土",
  ];
  return days[dayOfWeek];
}
GitHubで編集を提案

Discussion