まえがき
GASからカレンダー登録なんかの際に「第2金曜」や「当月最後の営業日」を取得したいといった時、どうしているでしょうか
パッと思いつく方法は、例えば以下のようなコードだと思います。
// 2回目に金曜(5)になるまでループ
const targetDate = new Date();
let count = 0;
targetDate.setDate(1);
targetDate.setHours(0,0,0); // 0時にする(しなくてもいい)
while(1){
if(targetDate.getDay() === 5){
count++;
}
if(count === 2){
break;
}
targetDate.setDate(targetDate.getDate() + 1);
}
console.log(targetDate); // 実行月の第2金曜の日付となる
これでも良いと思いますが、ループをしたり、カウンタを扱うのはちょっと嫌かな…ってお気持ちです。
本題
関数にしてしまう
まずは月の日付のDate配列を作ります。
引数を工夫すれば、指定月のカレンダー作成とかもできると思います。
function monthDates(){
const [y,m]=(new Date).toLocaleDateString().split('/');
return new Array(32).fill().map((_,d)=>new Date([y,m,d])).filter((d,i)=>d.getDate()===i)
}
使い方
この関数を実行すると、以下のような配列が得られます。
0: Wed Jan 01 2025 00:00:00 GMT+0900 (日本標準時) {}
1: Thu Jan 02 2025 00:00:00 GMT+0900 (日本標準時) {}
︙
29: Thu Jan 30 2025 00:00:00 GMT+0900 (日本標準時) {}
30: Fri Jan 31 2025 00:00:00 GMT+0900 (日本標準時) {}
length: 31
配列なので、フィルタするだけです。
// 第2金曜を取得する
const secondFriday = monthDates().filter(date=>date.getDay() === 5)[1];
// 最終営業日(平日)を取得する
const lastSalesDay = monthDates().filter(date=>!/[06]/.test(date.getDay()).slice(-1)[0];
// 毎週水曜日
const wednesdays = monthDates().filter(date=>date.getDay() === 3);
// 日付のテキストにする場合は、インデックスではなくparse関数を使います
monthDates().map(date=>String(date.getDate()));
// -> ['1', '2', '3', '4', '5', ...'31']
monthDates().map(date=>date.toLocaleString());
// -> ['2025/1/1 0:00:00', '2025/1/2 0:00:00', ...'2025/1/31 0:00:00']
解説
new Array(32).fill()
で未定義の値が32個の配列を作成し
map((_,d)=>new Date([y,m,d]))
でインデックスの値と、年・月の値を組み合わせてDateとして反映
filter((d,i)=>d.getDate()===i)
で当月の日付のみになるよう、日付とインデックスが一致する日だけにする
要素を32個作成するのは、インデックスの最初の値が0
であるためです。
31日まで無い月もあるので、フィルタで一緒に消します。
fill()しておかないと、map()が働かないみたいです。