先日作成したPHP版祝日取得クラス のJavaScript版です。
PHP版をJavaScriptに置き換えただけですので、使い方もほぼ同じです。
メソッドやプロパティについてはPHP版のほうを参照してください。
holiday_class.js
class Holiday {
constructor(year = 0) {
// 祝日定義
// ('国民の祝日に関する法律'が公布・施行された1948年7月20日以降のもののみ)
this.holidayDefinitions = {
1 : {
'1949:1' : '元日',
'1949:15, 2000:2_1'
: '成人の日',
},
2 : {
'1967:11' : '建国記念の日',
'2020:23' : '天皇誕生日',
'1989:24, 1990:0'
: '大喪の礼',
},
3 : {
'1949:s' : '春分の日',
},
4 : {
'1959:10, 1960:0'
: '結婚の儀',
'1949:29' : '天皇誕生日, 1989:みどりの日, 2007:昭和の日',
},
5 : {
'2019:1, 2020:0'
: '皇太子殿下即位・改元',
'1949:3' : '憲法記念日',
'2007:4' : 'みどりの日',
'1949:5' : 'こどもの日',
},
6 : {
'1993:9, 1994:0'
: '結婚の儀',
},
7 : {
'1996:20, 2003:3_1, 2020:23, 2021:22, 2022:3_1'
: '海の日',
'2020:24, 2021:23, 2022:0'
: 'スポーツの日',
},
8 : {
'2016:11, 2020:10, 2021:8, 2022:11'
: '山の日',
},
9 : {
'1966:15, 2003:3_1'
: '敬老の日',
'1948:a' : '秋分の日',
},
10 : {
'1966:10, 2000:2_1, 2020:0, 2022:2_1'
: '体育の日, 2020:スポーツの日',
'2019:22, 2020:0'
: '即位礼正殿の儀',
},
11 : {
'1948:3' : '文化の日',
'1990:12, 1991:0'
: '即位礼正殿の儀',
'1948:23' : '勤労感謝の日',
},
12 : {
'1989:23, 2019:0'
: '天皇誕生日',
},
};
this.dateTime = new Date();
this.dateTime.setHours(0, 0, 0);
if(year < 1) year = this.dateTime.getFullYear();
this.year = year;
this.month = this.dateTime.getMonth() + 1;
this.result = {};
this.useIndefiniteHoliday = 1;
this.resultType = 0;
}
/**
* 1年分のリストを返す
*/
getHolidayOfYear(year = 0) {
if(year < 1) year = this.year;
if(this.result[year] === undefined) {
// 該当年の祝日オブジェクトに変換
let holiday = {};
const equinox = .242194 * (year - 1980) - Math.floor((year - 1980) / 4);
for(const month in this.holidayDefinitions) {
holiday[month] = {};
const currentMonthData = this.holidayDefinitions[month];
for(const days in currentMonthData) {
const names = currentMonthData[days];
// 対象年・日取得
const _days = days.split(',');
const arrTmp = {};
for(const i in _days) {
const tmp = _days[i].split(':');
arrTmp[Number(tmp[0])] = tmp[1].trim();
}
let yearTmp = 0;
for(const tmp in arrTmp)
if(year >= tmp && tmp >= yearTmp) yearTmp = tmp;
if(yearTmp === 0) continue;
// 日を記述形式ごとに取得
let day;
if(arrTmp[yearTmp] === 's')
day = Math.floor(20.8431 + equinox);
else if(arrTmp[yearTmp] === 'a')
day = Math.floor(23.2488 + equinox);
else if(arrTmp[yearTmp].indexOf('_') >= 0) {
const [num, w] = arrTmp[yearTmp].split('_');
day = this.getDayOfNumWeek(year, month, num, w);
}
else
day = Number(arrTmp[yearTmp]);
if(day < 1) continue;
// 名称取得
const _names = names.split(',');
const arrTmpName = {};
for(const i in _names) {
const tmp = _names[i].split(':');
if(tmp.length === 1)
arrTmpName[0] = tmp[0].trim();
else
arrTmpName[Number(tmp[0])] = tmp[1].trim();
}
yearTmp = 0;
for(const tmp in arrTmpName)
if(year >= tmp && tmp >= yearTmp) yearTmp = tmp;
holiday[month][day] = (holiday[month][day] === undefined) ?
arrTmpName[yearTmp] : holiday[month][day] + ', ' + arrTmpName[yearTmp];
}
}
// 国民の休日・振替休日
if(this.useIndefiniteHoliday)
holiday = this.indefiniteHoliday(holiday, year);
this.result[year] = holiday;
}
return this.resultType ?
this.convertLinear(year, this.result[year]):
this.result[year];
}
/**
* 国民の休日・振替休日
*/
indefiniteHoliday(holiday, year) {
for(let month = 1; month <= 12; month++) {
// 月末日
this.dateTime.setFullYear(year, month, 0);
const lastDay = this.dateTime.getDate();
for(let day = 1; day <= lastDay; day++) {
// 前日の月日
this.dateTime.setFullYear(year, month - 1, day - 1);
const prevMonth = this.dateTime.getMonth() + 1;
const prevDay = this.dateTime.getDate();
// 翌日の月日
this.dateTime.setFullYear(year, month - 1, day + 1);
const nextMonth = this.dateTime.getMonth() + 1;
const nextDay = this.dateTime.getDate();
// 祝日に挟まれた平日を国民の休日に変更(1986年以降)
this.dateTime.setFullYear(year, month - 1, day);
if( year >= 1986 && // 1986年以降
holiday[prevMonth][prevDay] !== undefined && // 前日が祝日
holiday[nextMonth][nextDay] !== undefined && // 翌日が祝日
holiday[month][day] === undefined && // 当日が祝日ではない
this.dateTime.getDay() !== 0 // 当日が日曜ではない
) {
holiday[month][day] = '国民の休日';
}
// 振替休日(1973年4月以降)
if( (year > 1973 || (year == 1973 && month >= 4)) && // 1973年4月以降
holiday[month][day] !== undefined && // 祝日
this.dateTime.getDay() === 0 // 日曜
) {
// その日以降の直近の平日を振替休日に
for(let i = 1; i < 7; i++) {
this.dateTime.setFullYear(year, month - 1, day + i);
const m = this.dateTime.getMonth() + 1;
const d = this.dateTime.getDate();
if(holiday[m][d] === undefined) {
holiday[m][d] = '振替休日';
break;
}
}
}
}
}
return holiday;
}
/**
* year年 month月 第num w曜日に該当する日を返す
*/
getDayOfNumWeek(year, month, num, w) {
this.dateTime.setFullYear(year, month - 1, 1);
const firstDayWeek = this.dateTime.getDay();
return 1 + (num - 1) * 7 + (7 + w - firstDayWeek) % 7;
}
/**
* YYYY-MM-DDをキーとしたオブジェクトに変換
*/
convertLinear(year, array) {
const arrTmp = {};
for(const month in array) {
for(const day in array[month]) {
const names = array[month][day];
arrTmp[
String(year).padStart(4, '0') + '-' +
String(month).padStart(2, '0') + '-' +
String(day).padStart(2, '0')
] = names;
}
}
return arrTmp;
}
/**
* 1か月分のリストを返す
*/
getHolidayOfMonth(month = 0) {
if(month < 1 || month > 12) month = this.month;
const year = this.year;
// 該当年の結果が未取得であれば取得
if(this.result[year] === undefined)
this.getHolidayOfYear();
if(this.resultType) {
const arrTmp = {};
for(const day in this.result[year][month]) {
arrTmp[
String(year).padStart(4, '0') + '-' +
String(month).padStart(2, '0') + '-' +
String(day).padStart(2, '0')
] = this.result[year][month][day];
}
return arrTmp;
} else {
return this.result[year][month];
}
}
/**
* 国民の休日・振替休日 使用フラグ変更
*/
setUseIndefiniteHoliday(flg = 1) {
this.useIndefiniteHoliday = flg == 1 ? 1 : 0;
// 取得済みの結果をリセット
this.result = {};
}
/**
* 戻り値形式変更
*/
setResultType(flg = 0) {
this.resultType = flg == 0 ? 0 : 1;
}
/**
* 年変更
*/
setYear(year = 0) {
if(year < 1) year = new Date().getFullYear();
this.year = year;
}
}
####使用例####
const holiday = new Holiday;
// 年も同時に指定
//const holiday = new Holiday(2019);
// 国民の休日及び振替休日の使用指定(0:非使用 1:使用(デフォルト))
holiday.setUseIndefiniteHoliday(1);
// 戻り値形式変更メソッド
// 0: 月、日をキーとしたオブジェクト(デフォルト)
// 1: YYYY-MM-DDをキーとしたオブジェクト
holiday.setResultType(0);
// 1年分のリスト取得
// 引数は年、引数省略時は年プロパティの値を参照します
console.log(holiday.getHolidayOfYear());
// 1か月分のリスト取得
// 引数は月、引数省略時は実行時の月で取得します
// 年は年プロパティの値を参照します
console.log(holiday.getHolidayOfMonth());
// 戻り値をYYYY-MM-DD形式に変更
holiday.setResultType(1);
// 年プロパティ変更(引数省略時は現在の年で設定)
holiday.setYear(2019);
console.log(holiday.getHolidayOfYear());
console.log(holiday.getHolidayOfMonth(5));
年、月をキーにして取得したものは、こんな使い方をする場合に楽かと思います。
const year = 2020;
const month = 7;
const day = 24;
const holidayName = new Holiday(year).getHolidayOfMonth(month)[day];
console.log(
`${year}年${month}月${day}日は` +
(holidayName !== undefined ? `${holidayName}です` : '祝日ではありません')
);
####結果####
2020年7月24日はスポーツの日です