はいさい!オースティンやいびーん!んながんじゅーやいびーみ?
概要
JavaScriptのジェネレーター関数を使ってDate
オブジェクトの期間を月ごとの期間にして繰り返し処理を行う方法を紹介します。
ジェネレーター関数について
JavaScript開発者の多くはJavaScriptのジェネレーター関数を必要だと感じたことがないのではないでしょうか?
実際、ジェネレーターを使わずにやっていても優秀なJavaScript開発者としてやっていけるのだと思います。
しかし、ジェネレーター関数を自分のコーディング道具箱に加えると、時々助かることがあります。
ジェネレータ関数は、for...each
構文で使えるオブジェクトを返してくれる関数です。
つまり、半数処理プロトコルのオブジェクトを返す関数です。
半数処理プロトコルのオブジェクトで代表的な物をいえばArray
がもっとも一般に知れているかと思います。
そのArray
と同じような処理ができるオブジェクトを作ってくれるのは、Generator
なのです。
今回は、二つのDate
オブジェクトから成る期間の月ごと反復処理を、Generator
を使って行う方法を紹介します。
ジェネレーター関数の定義方法
ジェネレーター関数は以下のように定義します。
function* myGen(arg) {
yield "cake";
yield "is";
yield "yummy";
yield arg;
}
function
の後に*
がついているものはジェネレーター関数になります。yield
という不思議な単語が出てきますが、これは通常関数のreturn
だと考えればいいです。
上記のジェネレーター関数を試しにfor...each
で反復処理してみると以下のような結果になります。
const myIterator = myGen(47);
for (const result of myIterator) {
console.log(result);
}
このように簡単にジェネレーター関数が使えます。
ジェネレーター関数の中にwhile
構文も、for...each
構文も使えるので、yield
ごとになんらかの処理を施してから返すことができます。
今回の記事では触れませんが、非同期処理のジェネレーター関数も作れます。
Dateオブジェクトの月ごと反復処理
あまり時間がないので 単刀直入に解決法を紹介します。
export function* generateMonthlyInterval(start: Date, end: Date) {
const startYear = start.getFullYear();
const startMonth = start.getMonth();
const endYear = end.getFullYear();
const endMonth = end.getMonth();
if (startYear > endYear) throw Error("start year must be less than end year!");
if (startMonth > endMonth) throw Error("Start month must be less than end month!");
let currentMonth = startMonth;
let currentYear = startYear;
while (currentYear < endYear || currentMonth <= endMonth) {
const yieldDate = new Date()
yieldDate.setFullYear(currentYear);
yieldDate.setMonth(currentMonth);
yield yieldDate;
if (currentMonth === 11) {
currentMonth = 0;
currentYear++;
} else {
currentMonth++;
}
}
}
これをJavaScriptにコンパイルして以下のようなコードでテストします。
const interval = generateMonthlyInterval(new Date("2021/10/1"), new Date("2022/11/12"));
let months = 0;
for (const month of interval) {
console.log(month);
months++;
}
console.log("total months: ", months);
すると以下のように、開始と終了のDate
オブジェクトの間の月々の処理ができます。
まとめ
ジェネレーター関数を少し紹介してまいりましたがいかがでしょうか?
Python開発者なら、ジェネレーター関数が日常的に活躍するかと思いますが、JavaScriptでジェネレーターを使う場面はそんなにない気がします。
無闇に使う必要はないのですが、ジェネレーター関数でより簡潔に解決できる課題があるときに、この道具をぜひ活用していただければと思います。