日历生成逻辑

需求:显示6行7列的日历表 (日期部分)

分析:

1.确定某年某月的日历

2.分成三部分

  • 1.当前月份所有日期 1号到最后一号
  • 2.前一月部分
  • 3.后一月部分

3. 确定当前月最后一天

比如 获得2025年11月最后一天(也就是11月有几天)

ts 复制代码
lastdate = new Date(2025,11,0)
curMonthLastDay = lastdate.getDate()  //30

4.获取上一月最后一天

比如 获得2025年10月最后一天(也就是10月有几天)

ts 复制代码
lastdate = new Date(2025,10,0)
preMonthLastDay = lastdate.getDate()  //31

5.补充上一月部分

  • 1.确定当前月第一天 为周几
    比如 获得2025年11月第一天为周几
ts 复制代码
firstdate = new Date(2025,10,1)
firstdate.getDay()  //6 

//注意: 0代表周日

  • 2.根据日历 星期是从周日开始还是周一开始确定需要补充上一月的几天

    • 1.周日开始
      daysFromPreMonth = firstdat.getDay()
    • 2.周一开始
      daysFromPreMonth = (firstdate.getDay() + 6) % 7
  • 3.补充上一月部分

ts 复制代码
 let calendarDays=[];
for (let i = daysFromPreMonth  - 1, i >= 0 ; i-- ){
calendarDays.push({ date: preMonthLastDay - i; isCurrentMonth : false;})}

5.添加本月部分

ts 复制代码
  for (let i =  1, i <= curMonthLastDay  ; i++ ){
  calendarDays.push(
{
date:  i;
isCurrentMonth : true;
})
}

6.添加下个月的日期

ts 复制代码
const restDays = 42 - calendarDays.length
  for (let i =  1, i <= restDays ; i++ ){
  calendarDays.push(
{
date: i;
isCurrentMonth : false;
})
}

7.实际代码

ts 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双视图日历对比</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            padding: 20px;
        }

        .calendar-comparison {
            display: flex;
            gap: 30px;
            max-width: 900px;
            width: 100%;
            flex-wrap: wrap;
            justify-content: center;
        }

        .calendar-container {
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
            padding: 20px;
            width: 100%;
            max-width: 420px;
            transition: transform 0.3s ease;
        }

        .calendar-container:hover {
            transform: translateY(-5px);
        }

        .calendar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 1px solid #eaeaea;
        }

        .calendar-header h2 {
            margin: 0;
            color: #2c3e50;
            font-size: 1.4rem;
        }

        .nav-button {
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 50%;
            width: 36px;
            height: 36px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2rem;
            transition: background-color 0.2s;
        }

        .nav-button:hover {
            background-color: #2980b9;
        }

        .calendar-table {
            width: 100%;
            border-collapse: collapse;
        }

        .calendar-table th {
            background-color: #f8f9fa;
            padding: 12px 5px;
            text-align: center;
            font-weight: 600;
            color: #34495e;
            border: 1px solid #eaeaea;
        }

        .calendar-table td {
            border: 1px solid #eaeaea;
            padding: 12px 5px;
            text-align: center;
            height: 40px;
            vertical-align: middle;
            transition: all 0.2s;
            position: relative;
        }

        .current-month {
            background-color: white;
            color: #2c3e50;
        }

        .other-month {
            background-color: #f8f9fa;
            color: #bdc3c7;
        }

        .today {
            background-color: #e1f0fa;
            color: #2980b9;
            font-weight: bold;
            border: 1px solid #3498db;
        }

        .calendar-title {
            text-align: center;
            margin-bottom: 10px;
            color: #7f8c8d;
            font-size: 0.9rem;
            font-weight: 500;
        }

        @media (max-width: 768px) {
            .calendar-comparison {
                flex-direction: column;
                align-items: center;
            }

            .calendar-container {
                max-width: 100%;
            }
        }
    </style>
</head>

<body>
    <div class="calendar-comparison">
        <div class="calendar-container">
            <div class="calendar-title">周日开始的日历(传统)</div>
            <div class="calendar-header">
                <button class="nav-button" id="prevMonthLeft">←</button>
                <h2 id="monthYearLeft">2025年十一月</h2>
                <button class="nav-button" id="nextMonthLeft">→</button>
            </div>
            <table class="calendar-table">
                <thead>
                    <tr>
                        <th>日</th>
                        <th>一</th>
                        <th>二</th>
                        <th>三</th>
                        <th>四</th>
                        <th>五</th>
                        <th>六</th>
                    </tr>
                </thead>
                <tbody id="calendarBodyLeft">
                    <!-- 左侧日历内容将通过JavaScript动态生成 -->
                </tbody>
            </table>
        </div>

        <div class="calendar-container">
            <div class="calendar-title">周一开始的日历(国际标准)</div>
            <div class="calendar-header">
                <button class="nav-button" id="prevMonthRight">←</button>
                <h2 id="monthYearRight">2025年十一月</h2>
                <button class="nav-button" id="nextMonthRight">→</button>
            </div>
            <table class="calendar-table">
                <thead>
                    <tr>
                        <th>一</th>
                        <th>二</th>
                        <th>三</th>
                        <th>四</th>
                        <th>五</th>
                        <th>六</th>
                        <th>日</th>
                    </tr>
                </thead>
                <tbody id="calendarBodyRight">
                    <!-- 右侧日历内容将通过JavaScript动态生成 -->
                </tbody>
            </table>
        </div>
    </div>

    <script>
        // 当前显示的年份和月份
        let currentYear = new Date().getFullYear();
        let currentMonth = new Date().getMonth();

        // 月份名称数组
        const monthNames = ["一月", "二月", "三月", "四月", "五月", "六月",
            "七月", "八月", "九月", "十月", "十一月", "十二月"];

        // 初始化日历
        document.addEventListener('DOMContentLoaded', function () {
            updateCalendars();

            // 为所有导航按钮添加事件监听器
            document.getElementById('prevMonthLeft').addEventListener('click', goToPreviousMonth);
            document.getElementById('nextMonthLeft').addEventListener('click', goToNextMonth);
            document.getElementById('prevMonthRight').addEventListener('click', goToPreviousMonth);
            document.getElementById('nextMonthRight').addEventListener('click', goToNextMonth);
        });

        // 切换到上一个月
        function goToPreviousMonth() {
            currentMonth--;
            if (currentMonth < 0) {
                currentMonth = 11;
                currentYear--;
            }
            updateCalendars();
        }

        // 切换到下一个月
        function goToNextMonth() {
            currentMonth++;
            if (currentMonth > 11) {
                currentMonth = 0;
                currentYear++;
            }
            updateCalendars();
        }

        // 更新两个日历
        function updateCalendars() {
            generateCalendar('calendarBodyLeft', 'sunday', 'monthYearLeft');
            generateCalendar('calendarBodyRight', 'monday', 'monthYearRight');
        }

        // 生成日历的主要函数
        function generateCalendar(targetBodyId, startOfWeek, monthYearId) {
            // 更新月份和年份显示
            document.getElementById(monthYearId).textContent = `${currentYear}年 ${monthNames[currentMonth]}`;

            // 获取当前月的第一天
            const firstDay = new Date(currentYear, currentMonth, 1);

            // 获取当前月最后一天(即当前月的天数)
            const curMonthLastDay = new Date(currentYear, currentMonth + 1, 0).getDate();

            // 获取上一月最后一天(即上一月的天数)
            const prevMonthLastDay = new Date(currentYear, currentMonth, 0).getDate();

            // 获取当前月第一天是星期几(0代表周日,6代表周六)
            const firstDayOfWeek = firstDay.getDay();

            // 计算需要从上一月补充的天数
            let daysFromPrevMonth;
            if (startOfWeek === 'sunday') {
                // 周日开始的日历
                daysFromPrevMonth = firstDayOfWeek;
            } else {
                // 周一开始的日历
                daysFromPrevMonth = (firstDayOfWeek + 6) % 7;
            }

            // 创建日历数组
            const calendarDays = [];

            // 添加上一月的日期
            for (let i = daysFromPrevMonth - 1; i >= 0; i--) {
                calendarDays.push({
                    date: prevMonthLastDay - i,
                    isCurrentMonth: false
                });
            }

            // 添加当前月的日期
            for (let i = 1; i <= curMonthLastDay; i++) {
                calendarDays.push({
                    date: i,
                    isCurrentMonth: true
                });
            }

            // 计算并添加下一月的日期,使日历总天数为42天(6行×7列)
            const totalCells = 42;
            const remainingDays = totalCells - calendarDays.length;
            for (let i = 1; i <= remainingDays; i++) {
                calendarDays.push({
                    date: i,
                    isCurrentMonth: false
                });
            }

            // 获取今天日期,用于高亮显示
            const today = new Date();
            const isCurrentMonth = today.getFullYear() === currentYear && today.getMonth() === currentMonth;
            const todayDate = isCurrentMonth ? today.getDate() : -1;

            // 生成日历表格HTML
            const calendarBody = document.getElementById(targetBodyId);
            calendarBody.innerHTML = '';

            // 将日期数组分成6行,每行7天
            for (let i = 0; i < 6; i++) {
                const row = document.createElement('tr');

                for (let j = 0; j < 7; j++) {
                    const dayIndex = i * 7 + j;
                    if (dayIndex < calendarDays.length) {
                        const day = calendarDays[dayIndex];
                        const cell = document.createElement('td');
                        cell.textContent = day.date;

                        // 根据是否是当前月设置样式
                        if (day.isCurrentMonth) {
                            cell.classList.add('current-month');
                            // 如果是今天,添加高亮样式
                            if (day.date === todayDate) {
                                cell.classList.add('today');
                            }
                        } else {
                            cell.classList.add('other-month');
                        }

                        row.appendChild(cell);
                    }
                }

                calendarBody.appendChild(row);
            }
        }
    </script>
</body>

</html>
相关推荐
捕捉一只前端小白5 小时前
前端面试题(仅供参考)
html·css3·js
Aerelin6 小时前
豆瓣数据采集案例
前端·爬虫·python·js·playwright
旧梦吟11 小时前
脚本网页 推理游戏
算法·css3·html5·web app
Aerelin1 天前
爬虫playwright中的资源监听
前端·爬虫·js·playwright
摸爬滚打李上进1 天前
Pycharm编辑HTML文件注释问题
python·pycharm·django·bootstrap·html5
星光一影1 天前
原生社交app/工会/家族/语音房/直播社交/付费解锁聊天/广场好友圈子/一对一聊天交友
mysql·uni-app·php·html5·交友
Funny Valentine-js1 天前
web实验后端php测试文本
前端·javascript·php·html5·cookie·telnet·session
星光一影1 天前
知识付费系统源码,资源网站,支持pc和h5
mysql·职场和发展·php·创业创新·html5·程序员创富
by__csdn2 天前
Vue 2 与 Vue 3:深度解析与对比
前端·javascript·vue.js·typescript·vue·css3·html5