class jkCalendar { constructor(baseYear = 2024, baseMonth = 1, baseDay = 1) { this.tenkan = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']; this.jyuunishi = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']; this.goodDays = ['癸巳', '庚戌', '乙亥', '庚子', '甲子', '庚辰', '甲辰', '癸酉', '乙酉']; this.sanrinbou = { '亥': [1, 3, 7, 10], '寅': [2, 4, 8, 11], '午': [3, 6, 9, 12], }; this.baseDate = new Date(baseYear, baseMonth - 1, baseDay); this.solLun = []; this.sanrinbou = {}; } addLunMon(begin, end, lunMon) { this.solLun.push({ begin: begin, end: end, lunMon: lunMon }); } getEtoIndicesForDate(date) { const msPerDay = 24 * 60 * 60 * 1000; const daysElapsed = Math.floor((date.getTime() - this.baseDate.getTime()) / msPerDay); const tenkanIndex = (daysElapsed % 10 + 10) % 10; const jyuunishiIndex = (daysElapsed % 12 + 12) % 12; return [tenkanIndex, jyuunishiIndex]; } isSanrinbou(date, juunishi) { if (!(juunishi in this.sanrinbou)) { return false; } const d = date.getFullYear() * 10000 + date.getMonth() * 100 + date.getDay(); for (let e of this.solLun) { if (e.begin <= d && d <= e.end) { console.log(juunishi); return this.sanrinbou[juunishi].includes(e.lunMon); } } return false; } generateCalendar(year, month, targetSelector) { const firstDay = new Date(year, month - 1, 1); const daysInMonth = new Date(year, month, 0).getDate(); const monthEn = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][month - 1]; let calendarHtml = `

${year}${month}${monthEn}

`; for (let i = 0; i < firstDay.getDay(); i++) { calendarHtml += ''; } let [currentTenkanIndex, currentJyuunishiIndex] = this.getEtoIndicesForDate(firstDay); for (let day = 1; day <= daysInMonth; day++) { const currentDate = new Date(year, month - 1, day); const eto = this.tenkan[currentTenkanIndex] + this.jyuunishi[currentJyuunishiIndex]; const isGoodDay = (this.goodDays.includes(eto) && !this.isSanrinbou(currentDate, this.jyuunishi[currentJyuunishiIndex])) ? ' calendar__table--day-goodday' : ''; calendarHtml += ``; if ((day + firstDay.getDay()) % 7 === 0 && day !== daysInMonth) { calendarHtml += ''; } currentTenkanIndex = (currentTenkanIndex + 1) % 10; currentJyuunishiIndex = (currentJyuunishiIndex + 1) % 12; } calendarHtml += '
${day}
'; const elCalendar = document.querySelector(targetSelector); if (elCalendar) { elCalendar.innerHTML = calendarHtml; } } addCalendarPdfLink(link, label, size) { const $a = document.createElement('a'); $a.href = link; $a.target = '_blank'; $a.className = 'link__text--pdf'; $a.rel = 'noopener nofollow'; $a.textContent = `${label}(PDF ${size})`; document.querySelector('#jk-calendar--link') .append($a); } } const now = new Date(); const currentYear = now.getFullYear(); const currentMonth = now.getMonth() + 1; const jkCal = new jkCalendar(); jkCal.addLunMon(20241231,20250129,12);jkCal.addLunMon(20250129,20250228,1);jkCal.addLunMon(20250228,20250329,2);jkCal.addLunMon(20250329,20250428,3);jkCal.addLunMon(20250428,20250527,4);jkCal.addLunMon(20250527,20250625,5);jkCal.addLunMon(20250625,20250823,6);jkCal.addLunMon(20250823,20250922,7);jkCal.addLunMon(20250922,20251021,8);jkCal.addLunMon(20251021,20251120,9);jkCal.addLunMon(20251120,20251220,10);jkCal.addLunMon(20251220,20260119,11);jkCal.generateCalendar(currentYear, currentMonth, '#jk-calendar--a'); const nextMonth = currentMonth === 12 ? 1 : currentMonth + 1; const nextYear = currentMonth === 12 ? currentYear + 1 : currentYear; jkCal.generateCalendar(nextYear, nextMonth, '#jk-calendar--b'); jkCal.addCalendarPdfLink('https://www.daiken.jp/support/pdf/index/daiken_calendar2024.pdf', '上棟吉日カレンダー2024', '405KB');