かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JavaScript 月末の日付を取得したい

JavaScript で月末の日付を取得する方法のメモ

new Date(YYYY, MM, 0) で先月の最終日が取得できる

const date = new Date(2023, 1, 0);
date.toLocaleDateString();
// => '2023/1/31'

// 0日で月を 0  = 1月にすると前年の12月の最終日が取得できる
const date = new Date(2023, 0, 0);
date.toLocaleDateString();
// => '2022/12/31'

new Date の月は 0 〜 11 なので 0 が 1月

閏年も問題なく取れる

const isLeapYear = (year: string) => {
  const date = new Date(year, 2, 0);
  console.log(date.toLocaleDateString());
  return date.getDate() === 29; 
}

isLeapYear('2000');
// => '2000/2/29' => true
isLeapYear('2023');
// => '2023/2/28' => false
isLeapYear('2024');
// => '2024/2/29' => true

※ 年数は 4桁で入力しないと 0 〜 99 が 1900 〜 1999年にマッピングされてしまうので文字列で入力させている cf. Date() constructor - JavaScript | MDN

おまけ

逆に日付が過ぎていると、過ぎている日数分だけ翌月の日付になる

const checkDate = (year, month, date) => {
    return new Date(year, month - 1, date).toLocaleDateString();
};

checkDate(2023, 2, 30);
// => '2023/3/2'
checkDate(2023, 2, 31)
// => '2023/3/3'
checkDate(2023, 4, 31)
// => '2023/5/1'
checkDate(2023, 4, 33)
// => '2023/5/3'
checkDate(2023, 12, 31 + 20)
// => '2024/1/20'
checkDate(2023, 12, 31 + 31 + 30)
// => '2024/3/1'

※ 文字列で 2023/04/32 のようなどの月にも存在しない日を指定すると Invalid Date になるが、年・月・日を別にわたす方法だと 60日のような日でも過ぎているだけ後の日付が返される

月にマイナスの値を渡すと前月の日付になる

new Date(2023, -1, 1);
// => 2022/12/01
new Date(2023, -2, 1);
// => 2022/11/01
new Date(2023, -1, 0)
// =>2022/11/30

年にマイナスの値を渡すと 0 の時を除いて紀元前になる

0"0000" は 0年 (紀元前1年) にはならず 1900年にマッピングされる

new Date(0, 0, 1);
// => 1900/01/01
new Date("0000", 0, 1);
// => 1900/01/01
new Date(-1, 0, 1);
// => -0001/01/01 … -1年 = 紀元前2年
new Date(-1, -1, 1);
// => -0002/12/01 … '-0001/01/01' - 1ヶ月 => 紀元前3年 (-2年) 12月 1日
new Date(-1, 12, 1);
// => 0000/01/01 … '-0001/01/01' + 12ヶ月 => 紀元前1年 (0年) 1月 1日

※ 但し JavaScript の Date は 1970-01-01 からの経過時間で計算しているので、曜日などは必ずしも正しい訳では無い (途中でユリウス暦からグレゴリオ暦に変わってるし、閏年が無い期間と調整のために増やした期間とかもあるので…)

cf. JavaScript Date オブジェクトで紀元前の日付を扱いたい - かもメモ

まとめ

new Date(YYYY, MM, DD) は、与えられた日付が存在しない場合はプラスマイナス関わらず経過分を計算した日付が返される様になってるっぽい


[参考]