/* =========================================================
   営業日カレンダー
========================================================= */


/* =========================================================
   ★ 普段変更するのは基本的にここだけです
========================================================= */

/*
 * 会社独自の休業日
 *
 * 土曜日・日曜日・日本の祝日は
 * 自動的に休業日にします。
 *
 * ここには、
 *
 * ・お盆休み
 * ・年末年始
 * ・臨時休業
 *
 * などだけを入力してください。
 */


const companyHolidays = {

    /* =========================
       2026年 お盆
    ========================= */

    "2026-08-13": "お盆休み",
    "2026-08-14": "お盆休み",


    /* =========================
       2026年 年末
    ========================= */

    "2026-12-29": "年末年始休業",
    "2026-12-30": "年末年始休業",
    "2026-12-31": "年末年始休業",


    /* =========================
       2027年 年始
    ========================= */

    "2027-01-04": "年末年始休業"

};


/* =========================================================
   ★ 普段変更するのはここまでです
========================================================= */



/* =========================================================
   カレンダー開始
========================================================= */

function startBusinessCalendar() {

    const calendarArea =
        document.getElementById("calendar-area");


    /*
     * カレンダーのHTMLがないページでは
     * 何もしない
     */
    if (!calendarArea) {
        return;
    }


    /*
     * 二重表示防止
     */
    calendarArea.innerHTML = "";


    const today = new Date();


    /*
     * 今月＋翌月＋翌々月
     */
    for (let i = 0; i &lt; 3; i++) {

        const targetDate =
            new Date(
                today.getFullYear(),
                today.getMonth() + i,
                1
            );


        createCalendar(
            targetDate.getFullYear(),
            targetDate.getMonth(),
            today,
            calendarArea
        );

    }

}



/* =========================================================
   各月のカレンダー作成
========================================================= */

function createCalendar(
    year,
    month,
    today,
    calendarArea
) {


    const nationalHolidays =
        getJapanHolidays(year);


    /*
     * 月の外枠
     */
    const calendarBox =
        document.createElement(&quot;div&quot;);

    calendarBox.className =
        &quot;calendar-box&quot;;


    /*
     * 年月
     */
    const title =
        document.createElement(&quot;h3&quot;);

    title.className =
        &quot;calendar-title&quot;;

    title.textContent =
        year + &quot;年&quot; + (month + 1) + &quot;月&quot;;


    calendarBox.appendChild(title);



    /*
     * table
     */
    const table =
        document.createElement(&quot;table&quot;);

    table.className =
        &quot;calendar-table&quot;;


    /*
     * 曜日
     */
    const weekdays =
        [&quot;日&quot;, &quot;月&quot;, &quot;火&quot;, &quot;水&quot;, &quot;木&quot;, &quot;金&quot;, &quot;土&quot;];


    const thead =
        document.createElement(&quot;thead&quot;);


    const headerRow =
        document.createElement(&quot;tr&quot;);


    weekdays.forEach(function (weekday) {

        const th =
            document.createElement(&quot;th&quot;);

        th.textContent = weekday;

        headerRow.appendChild(th);

    });


    thead.appendChild(headerRow);

    table.appendChild(thead);



    /*
     * 日付部分
     */
    const tbody =
        document.createElement(&quot;tbody&quot;);


    const firstDay =
        new Date(
            year,
            month,
            1
        ).getDay();


    const lastDate =
        new Date(
            year,
            month + 1,
            0
        ).getDate();


    let day = 1;



    /*
     * 最大6週間
     */
    for (let week = 0; week &lt; 6; week++) {


        const tr =
            document.createElement(&quot;tr&quot;);


        for (
            let weekday = 0;
            weekday &lt; 7;
            weekday++
        ) {


            const td =
                document.createElement(&quot;td&quot;);


            /*
             * 月初前
             */
            if (
                week === 0 &amp;&amp;
                weekday  lastDate) {

                td.className = "empty";

                tr.appendChild(td);

                continue;

            }



            td.textContent = day;



            /*
             * 日曜日
             */
            if (weekday === 0) {

                td.classList.add("sunday");

            }


            /*
             * 土曜日
             */
            if (weekday === 6) {

                td.classList.add("saturday");

            }



            const dateString =
                makeDateString(
                    year,
                    month + 1,
                    day
                );



            /* =================================================
               休業日判定
            ================================================= */

            let isHoliday = false;

            let holidayName = "";



            /*
             * 土曜日・日曜日
             */
            if (
                weekday === 0 ||
                weekday === 6
            ) {

                isHoliday = true;

                holidayName =
                    weekday === 0
                        ? "日曜日"
                        : "土曜日";

            }



            /*
             * 日本の祝日
             */
            if (
                nationalHolidays.has(
                    dateString
                )
            ) {

                isHoliday = true;

                holidayName =
                    nationalHolidays.get(
                        dateString
                    );

            }



            /*
             * 会社独自休業
             */
            if (
                Object.prototype.hasOwnProperty.call(
                    companyHolidays,
                    dateString
                )
            ) {

                isHoliday = true;

                holidayName =
                    companyHolidays[
                        dateString
                    ];

                td.classList.add(
                    "company-holiday"
                );

            }



            /*
             * 休業日
             */
            if (isHoliday) {

                td.classList.add(
                    "holiday"
                );


                /*
                 * PCでマウスを合わせると
                 * 祝日名などが表示されます
                 */
                td.title =
                    holidayName;

            }



            /*
             * 今日
             */
            if (
                year ===
                    today.getFullYear() &amp;&amp;
                month ===
                    today.getMonth() &amp;&amp;
                day ===
                    today.getDate()
            ) {

                td.classList.add(
                    "today"
                );

            }



            tr.appendChild(td);

            day++;

        }


        tbody.appendChild(tr);


        if (day > lastDate) {
            break;
        }

    }



    table.appendChild(tbody);

    calendarBox.appendChild(table);

    calendarArea.appendChild(
        calendarBox
    );

}



/* =========================================================
   日本の祝日
========================================================= */

function getJapanHolidays(year) {


    const holidays =
        new Map();



    /* =====================================================
       固定祝日
    ===================================================== */

    addHoliday(
        holidays,
        year,
        1,
        1,
        "元日"
    );


    addHoliday(
        holidays,
        year,
        2,
        11,
        "建国記念の日"
    );


    addHoliday(
        holidays,
        year,
        2,
        23,
        "天皇誕生日"
    );


    addHoliday(
        holidays,
        year,
        4,
        29,
        "昭和の日"
    );


    addHoliday(
        holidays,
        year,
        5,
        3,
        "憲法記念日"
    );


    addHoliday(
        holidays,
        year,
        5,
        4,
        "みどりの日"
    );


    addHoliday(
        holidays,
        year,
        5,
        5,
        "こどもの日"
    );


    addHoliday(
        holidays,
        year,
        8,
        11,
        "山の日"
    );


    addHoliday(
        holidays,
        year,
        11,
        3,
        "文化の日"
    );


    addHoliday(
        holidays,
        year,
        11,
        23,
        "勤労感謝の日"
    );



    /* =====================================================
       ハッピーマンデー
    ===================================================== */

    addNthMondayHoliday(
        holidays,
        year,
        1,
        2,
        "成人の日"
    );


    addNthMondayHoliday(
        holidays,
        year,
        7,
        3,
        "海の日"
    );


    addNthMondayHoliday(
        holidays,
        year,
        9,
        3,
        "敬老の日"
    );


    addNthMondayHoliday(
        holidays,
        year,
        10,
        2,
        "スポーツの日"
    );



    /* =====================================================
       春分・秋分
    ===================================================== */

    const vernalDay =
        calculateVernalEquinox(
            year
        );


    if (vernalDay !== null) {

        addHoliday(
            holidays,
            year,
            3,
            vernalDay,
            "春分の日"
        );

    }



    const autumnDay =
        calculateAutumnEquinox(
            year
        );


    if (autumnDay !== null) {

        addHoliday(
            holidays,
            year,
            9,
            autumnDay,
            "秋分の日"
        );

    }



    /*
     * 本来の国民の祝日を保存
     */
    const originalNationalHolidays =
        new Map(holidays);



    /* =====================================================
       国民の休日
    ===================================================== */

    const startDate =
        new Date(
            year,
            0,
            2
        );


    const endDate =
        new Date(
            year,
            11,
            30
        );


    for (
        let date =
            new Date(startDate);

        date &lt;= endDate;

        date.setDate(
            date.getDate() + 1
        )
    ) {


        const currentKey =
            dateToString(date);


        if (
            originalNationalHolidays.has(
                currentKey
            )
        ) {

            continue;

        }


        const previousDate =
            new Date(date);


        previousDate.setDate(
            previousDate.getDate() - 1
        );


        const nextDate =
            new Date(date);


        nextDate.setDate(
            nextDate.getDate() + 1
        );


        const previousKey =
            dateToString(
                previousDate
            );


        const nextKey =
            dateToString(
                nextDate
            );


        if (
            originalNationalHolidays.has(
                previousKey
            ) &amp;&amp;
            originalNationalHolidays.has(
                nextKey
            )
        ) {

            holidays.set(
                currentKey,
                &quot;国民の休日&quot;
            );

        }

    }



    /* =====================================================
       振替休日
    ===================================================== */

    const nationalHolidayEntries =
        Array.from(
            originalNationalHolidays.keys()
        );


    nationalHolidayEntries.forEach(
        function (dateString) {


            const date =
                stringToDate(
                    dateString
                );


            /*
             * 日曜日でない場合は何もしない
             */
            if (
                date.getDay() !== 0
            ) {

                return;

            }


            let substituteDate =
                new Date(date);


            substituteDate.setDate(
                substituteDate.getDate() + 1
            );


            /*
             * 祝日が連続する場合は
             * その次まで進む
             */
            while (
                holidays.has(
                    dateToString(
                        substituteDate
                    )
                )
            ) {

                substituteDate.setDate(
                    substituteDate.getDate() + 1
                );

            }


            if (
                substituteDate.getFullYear()
                === year
            ) {

                holidays.set(
                    dateToString(
                        substituteDate
                    ),
                    &quot;振替休日&quot;
                );

            }

        }
    );


    return holidays;

}



/* =========================================================
   第○月曜日
========================================================= */

function addNthMondayHoliday(
    holidays,
    year,
    month,
    nth,
    name
) {


    const firstDay =
        new Date(
            year,
            month - 1,
            1
        );


    const firstWeekday =
        firstDay.getDay();


    const firstMonday =
        1 +
        (
            (8 - firstWeekday)
            % 7
        );


    const targetDay =
        firstMonday +
        (
            (nth - 1)
            * 7
        );


    addHoliday(
        holidays,
        year,
        month,
        targetDay,
        name
    );

}



/* =========================================================
   春分の日
========================================================= */

function calculateVernalEquinox(
    year
) {


    if (
        year  2099
    ) {

        return null;

    }


    return Math.floor(

        20.8431

        +

        0.242194
        *
        (year - 1980)

        -

        Math.floor(
            (year - 1980)
            / 4
        )

    );

}



/* =========================================================
   秋分の日
========================================================= */

function calculateAutumnEquinox(
    year
) {


    if (
        year  2099
    ) {

        return null;

    }


    return Math.floor(

        23.2488

        +

        0.242194
        *
        (year - 1980)

        -

        Math.floor(
            (year - 1980)
            / 4
        )

    );

}



/* =========================================================
   祝日登録
========================================================= */

function addHoliday(
    holidays,
    year,
    month,
    day,
    name
) {


    holidays.set(

        makeDateString(
            year,
            month,
            day
        ),

        name

    );

}



/* =========================================================
   YYYY-MM-DD
========================================================= */

function makeDateString(
    year,
    month,
    day
) {


    return (

        year

        +

        "-"

        +

        String(
            month
        ).padStart(
            2,
            "0"
        )

        +

        "-"

        +

        String(
            day
        ).padStart(
            2,
            "0"
        )

    );

}



/* =========================================================
   Date → YYYY-MM-DD
========================================================= */

function dateToString(date) {


    return makeDateString(

        date.getFullYear(),

        date.getMonth() + 1,

        date.getDate()

    );

}



/* =========================================================
   YYYY-MM-DD → Date
========================================================= */

function stringToDate(
    dateString
) {


    const parts =
        dateString.split("-");


    return new Date(

        Number(parts[0]),

        Number(parts[1]) - 1,

        Number(parts[2])

    );

}



/* =========================================================
   実行
========================================================= */

/*
 * WordPressではJavaScriptの読込位置によって
 * HTMLがまだ存在していない可能性があります。
 *
 * そのため両方に対応します。
 */

if (
    document.readyState ===
    "loading"
) {

    document.addEventListener(
        "DOMContentLoaded",
        startBusinessCalendar
    );

} else {

    startBusinessCalendar();

}