JavaScriptで、祝日を調べる(取得する)(明治からも対応)
ちょい書きかけ
う〜〜〜ん。明治とか大正の時代の休日も今どきとして必要なのか?
今さらながら、作ってから気づく。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> </style> </head> <body> <h3>六曜について</h3> <pre> n = (month + day) % 6; ary = ['大安', '赤口', '先勝', '友引', '先負', '仏滅']; rst = ary[n]; </pre> <script> { const CURRENT_DATE = new Date, CURRENT_YEAR = CURRENT_DATE.getFullYear (), TITLE_FURIKAE = '(振替休日)', TITLE_KOKUMIN = '(国民の休日)', SHUKUJITU_FUNC = [ // 国民の祝日 「祝日法」 1948-7-20施行 ganjitu, // 元日 seijin_no_hi, // 成人の日 kenkokukinen_no_hi, // 建国記念の日 shunbun_no_hi, // 春分の日 shouwa_tennou, // 昭和の日、みどりの日、昭和天皇誕生日 kenpou_kinenbi, // 憲法記念日 midori_no_hi, // みどりの日 kodomo_no_hi, // こどもの日 umi_no_hi, // 海の日 yama_no_hi, // 山の日 keirou_no_hi, // 敬老の日 shuubun_no_hi, // 秋分の日 taiiku_no_hi, // 体育の日 bunka_no_hi, // 文化の日 kinroukansha_no_hi, // 勤労感謝の日 heisei_tennou, //(平成)天皇誕生日 // 祝祭日 「年中祭日祝日ノ休暇日ヲ定ム」 1873-10-14施行 sihousetu, //四方節 - sinnenenkai, //新年宴会 kigensetu, //紀元節 tentyousetu, //天長節 tentyousetu_shukujitu, //天長節祝日 meijisetu, //明治節 gensisai, //元始祭 koumeitennousai, //孝明天皇祭 shunkikoureisai, //春季皇霊祭 jinmutennousai, //神武天皇祭 meijitennousai, //明治天皇祭 kannamesai, //神嘗祭 shuukikoureisai, //秋季皇霊祭 kannamesai2, //神嘗祭 niinamesai, //新嘗祭 taishoutennousai //大正天皇祭 ]; //_________________________________________________________________ //指定の年月のn週のw曜日の日にちを返す function getWN (year, month, week_num, day_num) { let d = new Date (year, month, 1), td = day_num - d.getDay () + 1; if (td <= 0) td += 7; td += 7 * (week_num - 1); return td; } //日付順にソート用 function sortByDate (a, b) { return a.date > b.date; } //次の日にする function nextDate (d = new Date, n = 1) { d.setDate (d.getDate () + n); return d; } //日付が等しいか function isSameDate (a, b) { let rst = (!a) || (!b) || (a.getFullYear () !== b.getFullYear ()) || (a.getMonth () !== b.getMonth ()) || (a.getDate () !== b.getDate ()); return !rst; } //年月日の属性を付加する function addYMDmethod (list) { for (let rec of list) { let d = rec.date; rec.year = d.getFullYear (); rec.month = d.getMonth () + 1; rec.day = d.getDate (); } return list; } //_________________________________________________________________ //元日 function ganjitu (y) { return 1948 < y ? {name: '元日', date: new Date (y, 0, 1)}: null; } //成人の日 function seijin_no_hi (y) { return 1948 < y ? {name: '成人の日', date: new Date (y, 0, y < 2000 ? 15: getWN (y, 0, 2, 1))}: null; } //建国記念の日 function kenkokukinen_no_hi (y) { return 1948 < y ? { name: '建国記念の日', date: new Date (y, 1, 11)}: null; } //春分の日 function shunbun_no_hi (y) { if (y <= 1948) return null; let d; if (y < 1980) d = parseInt(20.8357 + 0.242194 * ( y - 1980), 10) - parseInt((y - 1983) / 4, 10); else if (y < 2100) d = parseInt(20.8431 + 0.242194 * ( y - 1980), 10) - parseInt((y - 1980) / 4, 10); else if (y < 2150) d = parseInt(20.8510 + 0.242194 * ( y - 1980), 10) - parseInt((y - 1980) / 4, 10); else throw new Error ('範囲外です' + y); return { name: '春分の日', date: new Date (y, 2, d) }; } //天皇誕生日, みどりの日, 昭和の日 function shouwa_tennou (y) { return 1948 < y ? {name: y < 1989 ? '天皇誕生日': y < 2007 ? 'みどりの日': '昭和の日', date: new Date (y, 3, 29)}: null; } //憲法記念日 function kenpou_kinenbi (y) { return 1948 < y ? { name: '憲法記念日', date: new Date (y, 4, 3)}: null; } //みどりの日 function midori_no_hi (y) { return 2006 < y ? { name: 'みどりの日', date: new Date (y, 4, 4)}: null; } //こどもの日 function kodomo_no_hi (y) { return 1949 < y ? { name: 'こどもの日', date: new Date (y, 4, 5)}: null; } //海の日 function umi_no_hi (y) { return 1995 < y ? { name: '海の日', date: new Date (y, 6, 2002 < y ? getWN (y, 6, 3, 1): 20 )}: null; } //山の日 function yama_no_hi (y) { return 2015 < y ? {name: '山の日', date: new Date (y, 7, 11)}: null; } //敬老の日 function keirou_no_hi (y) { return 1965 < y ? {name: '敬老の日', date: new Date (y, 8, y < 2003 ? 15: getWN (y, 8, 3, 1))}: null; } //秋分の日 function shuubun_no_hi (y) { if (y < 1948) return null; //法の施行後 let d; if (y < 1980) d = parseInt(23.2588 + 0.242194 * (y - 1980), 10) - parseInt((y - 1983) / 4, 10); else if (y < 2100) d = parseInt(23.2488 + 0.242194 * (y - 1980), 10) - parseInt((y - 1980) / 4, 10); else if (y < 2150) d = parseInt(24.2488 + 0.242194 * (y - 1980), 10) - parseInt((y - 1980) / 4, 10); else throw new Error ('範囲外です'); return { name: '秋分の日', date: new Date (y, 8, d)}; } //体育の日 function taiiku_no_hi (y) { return 1965 < y ? {name: '体育の日', date: new Date (y, 9, y < 2000 ? 10: getWN (y, 9, 2, 1))}: null; } //文化の日 function bunka_no_hi (y) { return 1947 < y ? {name: '文化の日', date: new Date (y, 10, 3)}: null; } //勤労感謝の日 function kinroukansha_no_hi (y) { return 1947 < y ? {name: '勤労感謝の日', date:new Date (y, 10, 23)}: null; } //天皇誕生日 function heisei_tennou (y) { return 1988 < y ? y < 2019 ? { name: '天皇誕生日', date: new Date (y, 11, 23)}: null: null; } //振替休日 function furikaeKyuujitu (list = [ ]) { let furikae = [ ], prev = null; begin = +new Date (1973, 3, 12), //.getTime (); end = +new Date (2007, 0, 1); //.getTime () --> 2006/12/31:23:59:59:999? list.forEach (obj => { if (+obj.date < begin) return;//1973以前は振替休日がない let date = new Date (obj.date); //2006/12/31以前:国民の祝日が日曜のとき次の日は振替休日 if (+date < end) { if (0 === date.getDay ())//日曜 furikae.push ({name: TITLE_FURIKAE, date: nextDate (date)}); } //2007以降、国民の祝日が連続しており、その中に日曜が含まれるとき次の平日は振替休日 else { if (prev) { if (isSameDate (prev, date)) nextDate (prev); else { furikae.push ({name: TITLE_FURIKAE, date: prev}); prev = null; } } if (0 === date.getDay ()) prev = nextDate (date); } }); return furikae; } //国民の休日 function kokuminKyuujitu (list = [ ]) { if (! list.length) throw new Error (''); let kyuujitu = [ ], y = list[0].date.getFullYear ();//祝日の配列の最初のDATEを基準とする prv = null, begin = new Date (1985, 11, 27); //1986-2006の5月4日の特殊処理 if (1986 <= y && y <= 2006) kyuujitu.push ({ name: TITLE_KOKUMIN, date: new Date (y, 4, 4)}); //1985/12/27以降 for (let cur of list) { let date = new Date (cur.date); if (begin <= +date) { if (isSameDate (prv, date)) { if (1 < nextDate (prv, -1).getDay ()) kyuujitu.push ({name: TITLE_KOKUMIN, date: prv}); prv = nextDate (date, 2); } } } return kyuujitu; } //_________________________________________________________________ // 国民の祝日 「祝日法」 1948-7-20施行 //四方節 function sihousetu (y) {//法令で定められてはいない return 1873 < y ? y <= 1948 ? { name: '四方節', date: new Date (y, 0, 1) }: null: null; } //新年宴会 function sinnenenkai (y) { return 1873 < y ? { name: '新年宴会', date: new Date (y, 0, 5) }: null; } //紀元節 function kigensetu (y) { return 1873 < y ? { name: '紀元節', date: new Date (y, 1, 11) }: null; } //天長節 function tentyousetu (y) { let date; switch (true) { case y < 1874 : case y === 1912 : case 1948 < y : return null; break; case y < 1912 : date = new Date (y, 10, 3); break; case y < 1927 : date = new Date (y, 7, 31); break; case y < 1949 : date = new Date (y, 3, 29); break; default : throw new Error ('year = ' + y); break; } return { name: '天長節', date }; } //天長節祝日 function tentyousetu_shukujitu (y) { return 1913 <= y ? y <= 1926 ? { name: '天長節祝日', date: new Date (y, 9, 31) }: null: null; } //明治節 function meijisetu (y) { return 1927 <= y ? y < 1948 ? { name: '明治節', date: new Date (y, 10, 3) }: null: null; } //元始祭 function gensisai (y) { return 1873 < y ? y <= 1948 ? { name: '元始祭', date: new Date (y, 0, 3) }: null: null; } //孝明天皇祭 function koumeitennousai (y) { return 1873 < y ? y <= 1912 ? { name: '孝明天皇祭', date: new Date (y, 0, 30) }: null: null; } //春季皇霊祭 function shunkikoureisai (y) { return 1879 <= y ? y <= 1948 ? { name: '春季皇霊祭', date: new Date (y, 2, 21) }: null: null; } //神武天皇祭 function jinmutennousai (y) { return 1873 < y ? y <= 1948 ? { name: '神武天皇祭', date: new Date (y, 3, 3) }: null: null; } //明治天皇祭 function meijitennousai (y) { return 1913 <= y ? y <= 1926 ? { name: '明治天皇祭', date: new Date (y, 6, 30) }: null: null; } //神嘗祭 function kannamesai (y) { return 1873 <= y ? y <= 1878 ? { name: '神嘗祭', date: new Date (y, 8, 17) }: null: null; } //秋季皇霊祭 function shuukikoureisai (y) { return 1878 <= y ? y < 1948 ? { name: '秋季皇霊祭', date: new Date (y, 8, 23) }: null: null; } //神嘗祭(2) function kannamesai2 (y) { return 1879 <= y ? y < 1948 ? { name: '神嘗祭', date: new Date (y, 9, 17) }: null: null; } //新嘗祭 function niinamesai (y) { return 1873 <= y ? y < 1948 ? { name: '新嘗祭', date: new Date (y, 10, 23) }: null: null; } //大正天皇祭 function taishoutennousai (y) { return 1927 <= y ? y < 1948 ? { name: '大正天皇祭', date: new Date (y, 11, 25) }: null: null; } //_________________________________________________________________ //皇室慶弔行事 function kousitu_gyouji (y) { switch (y) { case 1915 : return [ {name: '即位の礼', date: new Date (y, 10, 10)}, {name: '大嘗祭', date: new Date (y, 10, 14)}, {name: '大饗第1日', date: new Date (y, 10, 16)} ]; break; case 1928 : return [ {name: '即位の礼', date: new Date (y, 10, 10)}, {name: '大嘗祭', date: new Date (y, 10, 14)}, {name: '大饗第1日', date: new Date (y, 10, 16)} ]; break; case 1959 : return [{name: '皇太子・明仁親王の結婚の儀', date: new Date (y, 3, 10)}]; break; case 1989 : return [{name: '昭和天皇の大喪の礼', date: new Date (y, 1, 24)}]; break; case 1990 : return [{name: '即位の礼正殿の儀', date: new Date (y, 10, 12)}]; break; case 1993 : return [{name: '皇太子・皇太子徳仁親王の結婚の儀', date: new Date (y, 5, 9)}]; break; case 2019 : return [ {name: '天皇の即位', date: new Date (y, 4, 1)}, {name: '即位の礼正殿の儀', date: new Date (y, 9, 22)} ]; break; default : return [ ]; } } //_________________________________________________________________ class Shukujitu { constructor (year = CURRENT_YEAR) { this.year = year; this.holidays = Shukujitu.getHolidayList (); } //_____ // arg0 = DateObject or Year(integer); //arg1 = 0〜11は月数、省略or -1 は、指定年のすべての祝日を返す static getHolidayList (date = CURRENT_DATE, month = -1) { if (! date instanceof Date) { if (Number.isInteger (date)) date = new Date (date, 0, 1); else throw new Error ('年数の値が範囲外'); } if (month < -1 || 12 < month) throw new Error ('月数の値が範囲外'); let year = typeof date === 'object' ? date.getFullYear (): date, holidays = [ ], furikae = [ ], kokumin = [ ], kousitu = [ ]; SHUKUJITU_FUNC.forEach (cbfunc => { let rst = cbfunc (year); if (rst) holidays.push (rst); }); holidays = holidays.sort (sortByDate); furikae = furikaeKyuujitu (holidays); kokumin = kokuminKyuujitu (holidays); kousitu = kousitu_gyouji (year);//皇室行事は祝日と重ならないのでこのまま混合する holidays = addYMDmethod (holidays.concat (furikae, kokumin, kousitu).sort (sortByDate)); if (-1 < month) holidays = holidays.filter (dt => month === dt.date.getMonth ()); return holidays; } } //_____ this.Shukujitu = Shukujitu; } //________________________________________________________ //実行サンプル Shukujitu.getHolidayList (2018, 10).forEach (a => a ? console.log (a.date.getFullYear(), a.date.getMonth () + 1, a.date.getDate (), a.name): null); </script>