LoginSignup
11
4

More than 3 years have passed since last update.

その月のx番目のy曜日の日付を求める式を1行で書く

Last updated at Posted at 2019-12-18

本記事はJavascript Advent Calendar 2019の19日目の記事です。

結論

ordinalNumber: x番目、1以上の整数
weekDay: y曜日、日曜日を0として0~6の整数
date: 指定の年月、javascriptの日付型、デフォルトで本日

function getDate(ordinalNumber, weekDay, date = new Date) {
  return ((7 * (ordinalNumber - 1) + 1) + (weekDay - new Date(date.getFullYear(), date.getMonth(), 1).getDay()) + (-(Math.sign(Math.sign(weekDay - new Date(date.getFullYear(), date.getMonth(), 1).getDay()) + 1) - 1) * 7)) * Math.sign(Math.sign(new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate() - ((7 * (ordinalNumber - 1) + 1) + (weekDay - new Date(date.getFullYear(), date.getMonth(), 1).getDay()) + (-(Math.sign(Math.sign(weekDay - new Date(date.getFullYear(), date.getMonth(), 1).getDay()) + 1) - 1) * 7))) + 1)
}

2019年12月19日付に実行した場合です

// 今月の第3木曜日
console.log(getDate(3,4)) // => 19
// 第5水曜日(1月1日)
console.log(getDate(5,3)) // => 0
// 2020年の体育の日(10月の第2月曜日)
console.log(getDate(2,1,new Date('2020/10'))) // => 12

なぜこの関数が生まれたのか

Googleカレンダーのこれを真似したいと思いました。
スクリーンショット 2019-12-19 7.35.28.png
この第x,y曜日という指定がどうしてもしたかったのです。あとはここから日付を求めればOK。
しかしその方法をいくらネットを探しても見当たらない。日付→第x,y曜日を求めるのはいくつか見つけましたが、私がほしいのはその逆関数。モジュールにdayjsを使ってたのですが、こちらにもない。なので仕方なく自作で作ることになりました。

で、どうせならワンライナーでまとめてみました。ワンライナーでまとめる意味全くないのですが。しかも見づらいし。ワンライナーなのに関数含めて3行という点はご了承ください。これを作ったのが2ヶ月近く前で、今見直しても解読できません。

作りとしては条件分岐が激しくあるので、かなりズルい手法ですが、Math.signを使ってゴリ押ししました。Math.signは正なら1、負なら-1、0なら0を返します。絶対ワンライナーで使うために作られた関数ではないですが。

格好良くワンライナーでまとめるよりは、素直に読めるコード書きましょう。

11
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4