最可靠的方式是直接调用LocalDate.lengthOfMonth(),它自动处理大小月、闰年二月(28或29天),无需手动维护月份天数表或if-else判断;结合getDayOfWeek()确定首日星期几以补齐空白格,再遍历生成日期列表,切换月份时实时重算,确保完全适配所有年份。

直接用 LocalDate.lengthOfMonth() 是获取当月天数最可靠的方式,它自动处理大小月、闰年二月(28 或 29 天),无需手动维护月份天数表或写一堆 if-else 判断。
核心逻辑:用 lengthOfMonth() 动态计算当月总天数
日历组件渲染前,先确定「当前显示的年份和月份」,然后调用:
int daysInMonth = LocalDate.of(year, month, 1).lengthOfMonth();
这行代码返回该月实际天数(如 2024 年 2 月返回 29,2023 年 2 月返回 28,4 月恒为 30)。它比 YearMonth.of(year, month).lengthOfMonth() 更轻量,且语义清晰。
补齐首尾空白格:结合 getDayOfWeek() 定位起始位置
日历通常以周日或周一为第一列。需知道当月 1 号是星期几,才能在前面补空格:
- 用
LocalDate.of(year, month, 1).getDayOfWeek().getValue()获取星期编号(周一=1,周日=7,符合 ISO 标准) - 若界面以周日为第一列,可转为
(dayOfWeek.getValue() % 7) + 1得到「周日=1,周一=2…」的偏移 - 空白格数量 = 起始列索引(0~6),用于生成占位节点或空 div
生成完整日期列表:从 1 到 lengthOfMonth() 遍历
有了总天数,就能安全生成日期数组,不依赖硬编码:
List<localdate> dates = IntStream.rangeClosed(1, daysInMonth)
.mapToObj(day -> LocalDate.of(year, month, day))
.collect(Collectors.toList());</localdate>
这个列表可直接绑定到 UI(如 RecyclerView item、Vue v-for 或 React useState),每个日期自带年月日信息,方便做高亮(今天)、禁用(未来不可选)、事件标记等。
切换月份时自动重算:避免缓存过期
用户点击「上月/下月」按钮时,不要复用旧的天数,而是重新构建新的 LocalDate 实例:
- 上月:
localDate.minusMonths(1)→ 再调.lengthOfMonth() - 下月:
localDate.plusMonths(1)→ 同样再调 - 避免把“2024-02”的天数(29)错误沿用到“2024-03”(31)
不复杂但容易忽略:只要每次渲染都基于当前年月实时调用 lengthOfMonth(),日历就能完全适配所有年份月份,包括 2100 年这种世纪闰年(Java 的 LocalDate 已按格里高利历正确实现)。










