🐕
GASの日直通知で休日をスキップする
やりたいこと
GoogleSpreadsheet + GAS + Slackで日直管理と通知 では指定した期間ごとに日直を通知していた。
しかし、現実には休日があり、それらの日はスキップしたい。
解:計算した次回通知日が休日の場合は次の候補にする
前回の記事では以下のコードで次回通知日を計算していた。
// work は { "name": "朝会司会", "intervals": 1, "next": '2025-05-23' } のようなオブジェクト
// intervalsは通知間隔日数
// nextは次回通知日のDateオブジェクト
function calculateNextDate(work) {
const nextDate = work.next
return new Date(nextDate.setDate(nextDate.getDate() + work.intervals))
}
これを、次回通知日が休日の場合に、さらに intervals
を休日にならない日が取得できるまで加算することで実現できる。
休日には2種類あり、「機械的に判断できるもの」と「機械的に判断できないもの」がある。
それぞれについて対方法を考える。
機械的に判断できるもの
「法定休日」と「法定外休日」があり、会社により曜日を指定して運用されていることが多い。
そのため、Dateオブジェクトの曜日でこれらは判定できる。
例えば、土日休みの場合は次のようになる。
const date = new Date()
const isWeekend = date.getDay() === 0 || date.getDay() === 6
機械的に判断できないもの
日本の場合、内閣府により「国民の祝日」が定められている。
これらはの中には日付や曜日で判定するには難しいものがあり、例えば「海の日」は 2025-07-21
と 2026-07-20
と年によって違う。
また、会社によっては「創業記念日」や「夏期休暇」、「年末年始休暇」など独自に定義した休日が存在することがある。
これらについては、シートで定義して管理し、コードから呼び出して判定処理に組み込むのが簡単である。
国民の祝日については、 内閣府の 国民の祝日について のページからCSVをダウンロードできる。1955年から全て掲載されているので必要な部分だけ残して、インポートなりコピー&ペーストする。
会社独自の休日については、調べてシートに記載する。
例えば holidays
という名前でシートを作成し、以下のような定義を記述する。
date | name |
---|---|
2025/1/1 | 元日 |
2025/1/13 | 成人の日 |
2025/2/11 | 建国記念の日 |
判定のためのコードは以下のようになる。
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('holidays')
const [header, ...rows] = sheet.getDataRange().getValues()
const holidays = rows.map(row => Object.fromEntries(header.map((key, i) => [key, row[i]])))
const date = new Date()
const isHoliday = holidays.some(holiday => holiday.date.getFullYear() === date.getFullYear() && holiday.date.getMonth() === date.getMonth() && holiday.date.getDate() === date.getDate())
休日を判定するコード
上記2点を反映したコードは以下のようになる。
function calculateNextDate(work) {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('holidays')
const [header, ...rows] = sheet.getDataRange().getValues()
const holidays = rows.map(row => Object.fromEntries(header.map((key, i) => [key, row[i]])))
let nextDate = work.next
nextDate = new Date(nextDate.setDate(nextDate.getDate() + work.intervals))
while (true) {
if (
nextDate.getDay() !== 0 && //日曜でない
nextDate.getDay() !== 6 && //土曜でない
!holidays.some(holiday =>
holiday.date.getFullYear() === nextDate.getFullYear() &&
holiday.date.getMonth() === nextDate.getMonth() &&
holiday.date.getDate() === nextDate.getDate()
) //シートに定義した休日ではない
) {
return nextDate
}
nextDate = new Date(nextDate.setDate(nextDate.getDate() + work.intervals))
}
}
Discussion