はじめに
Cloud Scheduler
で、毎月第一月曜日とか毎月第一営業日とかにジョブを実行 (Pub/Subトピックにメッセージを送信) する方法が分からなかったので、備忘録として残しておく。
ドキュメントには、
Unix cron 形式でスケジュールを定義して、1 日に複数回ジョブを実行したり、1 年のうちの特定の日や月にジョブを実行したりできます。
と書かれてある。
が、cronの仕様だと、同時に 日にち と 曜日 の指定をすると、
ANDではなくOR条件になるみたいなので一筋縄ではいかなさそう。
第一営業日を判定する関数の作成
isFirstBusinessDayOfMonth.ts
const MONTHS = {
JAN: 0,
FEB: 1,
MAR: 2,
APR: 3,
MAY: 4,
JUN: 5,
JUL: 6,
AUG: 7,
SEP: 8,
OCT: 9,
NOV: 10,
DEC: 11,
} as const;
const NATIONAL_HOLIDAYS = [
new Date(2023, MONTHS.JAN, 1), // 元日
new Date(2023, MONTHS.JAN, 2), // 振替休日
new Date(2023, MONTHS.JAN, 9), // 成人の日
new Date(2023, MONTHS.FEB, 11), // 建国記念の日
new Date(2023, MONTHS.FEB, 23), // 天皇誕生日
new Date(2023, MONTHS.MAR, 21), // 春分の日
new Date(2023, MONTHS.APR, 29), // 昭和の日
new Date(2023, MONTHS.MAY, 3), // 憲法記念日
new Date(2023, MONTHS.MAY, 4), // みどりの日
new Date(2023, MONTHS.MAY, 5), // こどもの日
new Date(2023, MONTHS.JUL, 17), // 海の日
new Date(2023, MONTHS.AUG, 11), // 山の日
new Date(2023, MONTHS.SEP, 18), // 敬老の日
new Date(2023, MONTHS.SEP, 23), // 秋分の日
new Date(2023, MONTHS.OCT, 9), // スポーツの日
new Date(2023, MONTHS.NOV, 3), // 文化の日
new Date(2023, MONTHS.NOV, 23), // 勤労感謝の日
];
const isSaturday = (date: Date): boolean => date.getDay() === 6;
const isSunday = (date: Date): boolean => date.getDay() === 0;
const isNationalHoliday = (date: Date): boolean => NATIONAL_HOLIDAYS.includes(date);
export const isFirstBusinessDayOfMonth = (date: Date): boolean => {
let firstBusinessDayOfMonth = new Date(
date.getFullYear(),
date.getMonth(),
1
);
while (
isSaturday(firstBusinessDayOfMonth) ||
isSunday(firstBusinessDayOfMonth) ||
isNationalHoliday(firstBusinessDayOfMonth)
) {
firstBusinessDayOfMonth = new Date(
firstBusinessDayOfMonth.getFullYear(),
firstBusinessDayOfMonth.getMonth(),
firstBusinessDayOfMonth.getDate() + 1
);
}
return (
date.getFullYear() === firstBusinessDayOfMonth.getFullYear() &&
date.getMonth() === firstBusinessDayOfMonth.getMonth() &&
date.getDate() === firstBusinessDayOfMonth.getDate()
);
};
スケジュールの指定
index.ts
import * as functions from 'firebase-functions';
import { isFirstBusinessDayOfMonth } from './your/path';
export const someFuncExec = functions
.region('asia-northeast1')
.runWith({
memory: '1GB',
timeoutSeconds: 300,
})
.pubsub.schedule('0 9 * * 1-5') // ここでは複雑な指定ができないため、平日9:00に実行するように指定
.timeZone('Asia/Tokyo')
.onRun(() => {
const today = new Date();
if (!isFirstBusinessDayOfMonth(today)) { // ここで先ほど作った関数を利用し、第一営業日じゃなかったら実行をスキップする
return Promise.resolve();
}
return handleSomeFunc();
});
以上、CloudSchedulerで毎月第一営業日にジョブを実行する方法の備忘録でした。
参考