カレンダーや締め日の処理などで、「その月の最終日(月末日)」を取得したい場面はよくあります。JavaScriptでは Date オブジェクトの特性を使って、1行で取得できます。
この記事では、定番のイディオムから、混乱しやすい「月の数え方(0始まり)」、そして月の日数の取得まで、つまずかない書き方を解説します。
new Date(year, month, 0) で取得できます(month は人間の月=1〜12でOK)。「日にち」に 0 を渡すと前日、つまり前月の末日になる仕組みです。.getDate() を付ければその月の日数(28〜31、うるう年も自動)が得られます。最短の書き方:new Date(year, month, 0)
もっとも簡潔なのは new Date(year, month, 0) です。月は人間の感覚どおり 1〜12 で渡せます(後述の理由で +1 は不要)。
// month は人間の月(1〜12)
function getLastDay(year, month) {
return new Date(year, month, 0);
}
const d = getLastDay(2024, 8); // 2024年8月
console.log(d.getDate()); // 31
仕組みと月の数え方(0始まりに注意)
なぜ month に +1 がいらないのか、仕組みを押さえておきましょう。Date の月は0始まり(0=1月 … 11=12月)ですが、「日にち」に 0 を渡すと、その月の前日=前月の末日になります。
new Date(2024, 8, 0); // 月index8=9月の「0日目」→ 2024年8月31日 new Date(2024, 0, 0); // 月index0=1月の「0日目」→ 2023年12月31日 // 人間の月8(8月)を渡すと、月index8(9月)の0日目=8月末になる // だから「人間の月」をそのまま渡せばよい
Date から getMonth() で取った値は0始まり(0〜11)です。その値を使うなら new Date(year, monthIndex + 1, 0) のように +1 します。「人間の月(1〜12)を直接渡すなら +1 不要」「getMonth()の値を使うなら +1 必要」と整理すると混乱しません。YYYY/MM/DD形式にする
取得した Date を YYYY/MM/DD 形式の文字列にします。1桁の月日は padStart(2, "0") でゼロ埋めします。
function formatYMD(date) {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, "0");
const d = String(date.getDate()).padStart(2, "0");
return `${y}/${m}/${d}`;
}
formatYMD(new Date(2024, 8, 0)); // "2024/08/31"
現在の日付を YYYY/MM/DD で取得・表示する方法は現在の日付をYYYY/MM/DD形式で取得・表示する方法で詳しく解説しています。
月の日数を取得する(うるう年も自動)
同じ仕組みで、その月が何日あるかも取れます。月末日の「日」がそのまま日数なので、.getDate() を付けるだけです。うるう年の2月(29日)も自動で正しく返ります。
function daysInMonth(year, month) {
return new Date(year, month, 0).getDate();
}
daysInMonth(2024, 2); // 29(うるう年は自動で29)
daysInMonth(2023, 2); // 28(平年)
daysInMonth(2024, 4); // 30
自分でうるう年を判定する必要がないのが Date を使う利点です。
今月の月末日を取得する
現在の日付から今月の月末日を取るには、getFullYear() と getMonth() を使います。getMonth() は0始まりなので +1 します。
const now = new Date(); // getMonth() は0始まり → +1 して「翌月の0日目」= 今月末 const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0); console.log(formatYMD(lastDay)); // 例: "2024/08/31"
なお new Date(年, 月, 日) はローカル時間で作られるため、文字列をパースするときのタイムゾーンのズレを気にせず日付を扱えます(文字列パースの注意点は文字列をDate型に変換する方法、日付の妥当性チェックは日付が正しいかチェックする方法を参照)。
よくある質問(FAQ)
new Date(year, month, 0) で取得できます。month に人間の月(1〜12)を渡せば、その月の末日の Date が返ります。日にちに 0 を渡すと前月の末日になる仕組みです。new Date(year, month, 0).getDate() で取得できます。月末日の「日」がそのまま日数(28〜31)になります。うるう年の2月も自動で29を返します。+1 不要です。一方 getMonth() で取った値(0〜11)を使う場合は +1 してnew Date(year, monthIndex + 1, 0) とします。new Intl.DateTimeFormat("ja-JP").format(date) で「2024/08/31」形式の文字列が得られます。year/month/day を "2-digit" 指定すると自動でゼロ埋めされます。まとめ
月末日は new Date(year, month, 0) で1行で取得できます。人間の月(1〜12)をそのまま渡せるのがこの書き方の利点で、.getDate() を付ければその月の日数(うるう年も自動)が得られます。
ポイントは、Date の月が0始まりであること。人間の月を直接渡すなら +1 不要、getMonth() の値を使うなら +1 必要、と覚えておけば混乱しません。フォーマットは padStart でゼロ埋めしましょう。
