LoginSignup
0
1

More than 5 years have passed since last update.

JavaScriptでプレミアムフライデーやハッピーマンデーを調べる

Last updated at Posted at 2017-03-13

月末の金曜日に決まったプレミアムフライデーは、あまりよい評判が聞こえません。ハッピーマンデーは、月曜日に移された国民の祝日です。何年何月の何番目の何曜日という引数から、当てはまる日付が返るJavaScriptの関数(getNthDay())を定めてみましょう。

getNthDay(年, 月, 序数, 曜日)

01 月初と月末のDateオブジェクトを得る

たとえば、2017年3月の月初のDateオブジェクトは、つぎのJavaScriptコードで得られます。月は0からはじまる連番整数であることに注意しましょう。

var date = new Date(2017, 2, 1);

では、その前の2月の月末はどうでしょう。実は、Date()コンストラクタの日に0を与えると、前月末のオブジェクトがつくられるのです(MDN「Date.prototype.setDate()」の「説明」参照)。

var date = new Date(2017, 2, 0);
console.log(date);  // Tue Feb 28 2017 00:00:00 GMT+0900 (JST)

02 年・月・序数・曜日から日付を返す関数

年・月・序数・曜日の4つの引数から日付を返す関数(getNthDay())は、つぎのように定められます。何番目という序数は、曜日と同じく0からはじめます。3月のプレミアムフライデー(第5金曜日)は、年度末の31日でした。

function getNthDay(year, month, ordinal, day) {
    var date;
    date = new Date(year, month - 1, 1);
    day = (day - date.getDay() + 7) % 7 + ordinal * 7;  // 日を導く
    date.setDate(date.getDate() + day);
    return date;
}
var date = getNthDay(2017, 3, 4, 5);
console.log(date.toString());  // Fri Mar 31 2017 00:00:00 GMT+0900 (JST)

関数の考え方はつぎのとおりです。剰余演算子%を用いた1行の式で、日を導いています。

  1. 月初の曜日を調べる
  2. その月の求めたい曜日のはじめ(第1)の日付を知る
  3. 序数にもとづいて7の倍数を加える

03 序数を月末から数えられるようにする

プレミアムフライデーは月末です。すると、序数を月末からさかのぼって数えられるようにした方が便利でしょう。この場合、引数を負にします。月初と月末で、数えはじめと序数が負という違いはあるものの、前項と考え方は同じです。

function getNthDay(year, month, ordinal, day) {
    var date;
    if (ordinal > -1) {
        date = new Date(year, month - 1, 1);
        day = (day - date.getDay() + 7) % 7 + ordinal * 7;
    } else {
        date = new Date(year, month, 0);
        day = (day - date.getDay() - 7) % 7 + (ordinal + 1) * 7;
    }
    date.setDate(date.getDate() + day);
    return date;
}
var date = getNthDay(2017, 3, -1, 5);
console.log(date.toString());  // Fri Mar 31 2017 00:00:00 GMT+0900 (JST)

04 月を超えないようにする

仕上げに、序数で月を超えないようにします。たとえば、3月に第6金曜日はありません。そのの場合には、つぎのコード001はnullを返すこととしました。併せて、TypeScriptの構文も掲げておきましょう。

コード001

function getNthDay(year, month, ordinal, day) {
    var date;
    var thisMonth;
    if (ordinal > -1) {
        date = new Date(year, month - 1, 1);
        thisMonth = date.getMonth();
        day = (day - date.getDay() + 7) % 7 + ordinal * 7;
    } else {
        date = new Date(year, month, 0);
        thisMonth = date.getMonth();
        day = (day - date.getDay() - 7) % 7 + (ordinal + 1) * 7;
    }
    date.setDate(date.getDate() + day);
    if (thisMonth !== date.getMonth()) {
        return null;
    }
    return date;
}
0
1
0

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
0
1