You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正日历组件中上月最后几天的位置渲染错误?

问题描述

尝试在日历中渲染上月的最后几天,但这些日期并未显示在正确的方格中。理想状态下,周二方格应显示31号、周一方格显示30号,以此类推。请问该如何修改代码,使日期对应到正确的方格中?

代码片段

JavaScript

let nav = 0;

const getCalendar = document.getElementById("calendar");

const weekDays = [
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
];

function nextButton() {
  document.getElementById("nextButton")?.addEventListener("click", () => {
    nav++;
    render();
  });
}

function backButton() {
  document.getElementById("backButton")?.addEventListener("click", () => {
    nav--;
    render();
  });
}

function render() {
  const dt = new Date();

  if (nav !== 0) {
    dt.setMonth(new Date().getMonth() + nav);
  }

  const day = dt.getDate();
  const month = dt.getMonth();
  const year = dt.getFullYear();
  const firstDayOfMonth = new Date(year, month, 1);
  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const lastDateOfLastMonth = new Date(year, month, 0).getDate();

  const dateString = firstDayOfMonth.toLocaleString("en-us", {
    weekday: "long",
    year: "numeric",
    month: "numeric",
    day: "numeric",
  });

  const getFirstDayMonth = dateString.split(", ")[0]; // Wednesday
  const days = weekDays.indexOf(getFirstDayMonth);

  (
    document.getElementById("month-heading")
  ).innerText = 
  `${dt.toLocaleDateString("en-us", { month: "long" })} ${year}`;
  
  getCalendar.innerHTML = "";

  for (let i = 1; i <= days + daysInMonth; i++) {
    const square = document.createElement("div");
    square.classList.add("day");

    const addedDay = i - days;

    /**
     * if the index is greater than the first day of the month add text for numbers
     *
     * else add padding squares
     */

    if (i > days) {
      square.innerText = addedDay;

      if (addedDay === day && nav === 0) {
        square.id = "currentDay";
      }
    } else {


      // enter the last few days of last month here this is where i might be doing 
      // something wrong 


      square.innerText = lastDateOfLastMonth - i + 1;

      // square.classList.add("padding");
    }
    getCalendar?.appendChild(square);
  }
}

nextButton();
backButton();

render();

CSS

/* CSS may differ from original */
body {
  font-family: sans-serif;
}
#header {
  margin-bottom: 1rem;
}
h1 {
  font-size: 1.2rem;
}
#weekdays, #calendar {
  display: grid;
  grid-template-columns: repeat(7, 6rem [col-start]);
}
.day, #weekdays > div {
  width: 6rem;
}
#weekdays > div {
  border-bottom: thin solid gray;
  border-top: thin solid gray;
  margin-bottom: 1rem;
}

.day {
  border: thin solid gray;
  height: 6rem;
}

HTML

<div class="container">
  <div class="calendar-body">
    <div id="header">
      <h1 id="month-heading"></h1>
      <div>
        <button id="backButton">Back</button>
        <button id="nextButton">Next</button>
      </div>
    </div>
    <div id="weekdays">
      <div>Sunday</div>
      <div>Monday</div>
      <div>Tuesday</div>
      <div>Wednesday</div>
      <div>Thursday</div>
      <div>Friday</div>
      <div>Saturday</div>
    </div>
    <div id="calendar"></div>
  </div>
</div>
解决方案

问题出在你计算上月日期的表达式上,当前的lastDateOfLastMonth - i + 1会让日期顺序颠倒。比如当月第一天是周三(days=3)、上月最后一天是31号时,i=1(周日)会显示31,i=2(周一)显示30,i=3(周二)显示29,和你需要的顺序完全相反。

修改else块中的日期计算逻辑,换成以下表达式即可:

square.innerText = lastDateOfLastMonth - days + i;

同时建议给上月日期添加样式类,方便区分:

square.classList.add("padding");

修改后的完整else块代码:

} else {
  square.innerText = lastDateOfLastMonth - days + i;
  square.classList.add("padding");
}

原理说明

  • days是当月第一天在weekDays中的索引(比如周三对应3),代表需要填充的上月日期数量。
  • lastDateOfLastMonth - days得到上月需要显示的起始日期(比如31-3=28,加上i从1到3,就得到29、30、31)。
  • 加上i后,就能按周日到周二的顺序依次显示29、30、31,完全匹配你的需求。

内容的提问来源于stack exchange,提问作者BARNOWL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:49:56