ISO 8601と言えば日付や時刻を20190624
や2019-06-24
、2019-06-24T09:00:00+09:00
というように表現する規格だ。
ISO 8601では日付を表す方法は一般的な年月日による表現の他にも以下のような表現が用意されている。
- 年とその年の1月1日からの経過日数 (例:
2019-175
) - 年と週番号、曜日番号(1=月曜日, 7=日曜日) (例:
2019-W26-1
)
今回は JavaScript を用いて、渡されたDate
からISO 8601の週番号を用いた文字列を返す関数を作成する。
定義
週番号を用いた表記は以下のように定義される
- 一週間は月曜日で始まり、日曜日で終わる
- その年の第一週は最初の木曜日を含む週
- そのため年の境目では、年月日の場合と異なる年を表記する場合がある (例: 2018年12月31日は
2019-W01-1
となる)
実装
function dateToIso8601Week(date){
// 引数のDateと同じ週の木曜日を計算
// 259200000 = 3days * 24hour * 60min * 60s * 1000ms
// 604800000 = 1week * 7days * 24hour * 60min * 60s * 1000ms
const thursday = new Date(Math.ceil((date.getTime() - 259200000) / 604800000) * 604800000);
// 木曜日と同じ年の1月1日を計算
const firstDayOfYear = new Date(thursday.getFullYear(), 0, 1);
// 木曜日がその年の第何週かを計算する
const weekOfYear = Math.floor((thursday.getTime() - firstDayOfYear.getTime()) / 604800000) + 1;
// 曜日をISO 8601に直す (jsは0=日~6=金、ISO 8601は1=月~7=日)
const dayOfWeek = date.getDay() !== 0 ? date.getDay() : 7;
// yyyy-Www-D 形式に直す
return `${thursday.getFullYear()}-W${('0' + weekOfYear).slice(-2)}-${dayOfWeek}`;
}
// input: 2018-12-31
// output: 2019-W01-1
console.log(dateToIso8601Week(new Date(2018, 11, 31)));