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

如何用Java编写循环打印指定年份的完整月历(含日期)

问题分析与修复方案

你的代码存在几个关键问题,导致无法正确打印全年日历,以下是问题点及修复后的完整代码:

核心问题点

  • 静态变量month误用:类中private static int month;为静态变量,会被所有Month实例共享,导致月份值混乱,应改为实例变量。
  • getAllMonths方法冗余错误:该方法直接打印所有月份名称,破坏了日历的排版逻辑,需删除。
  • printCalendar仅支持单月打印:原方法只能打印单个月份,需要调整为遍历12个月生成全年日历。
  • 月份标题打印错误:原代码直接打印MONTHS数组对象,会输出无效字符串,需改为MONTHS[month]获取对应月份名称。
  • main方法初始化错误:传入未初始化的静态month变量,导致初始月份为0(无效月份),需循环处理1-12月。

修复后的完整代码

import java.util.Scanner;

public class YearCalendar {
    private static final String[] MONTHS = {
            "", "January", "February", "March", "April", "May", "June", "July",
            "August", "September", "October", "November", "December"
    };

    private static final int[] NUMDAYS = {
            0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };

    private int month;
    private int year;

    public YearCalendar(int month, int year) {
        this.month = month;
        this.year = year;
    }

    private boolean isLeapYear() {
        if (year % 400 == 0) {
            return true;
        }
        if (year % 100 == 0) {
            return false;
        }
        return year % 4 == 0;
    }

    private int getNumDays() {
        if (month == 2) {
            return isLeapYear() ? 29 : 28;
        } else {
            return NUMDAYS[month];
        }
    }

    private int getStartDOW() {
        int m, y;
        if (month < 3) {
            m = month + 12;
            y = year - 1;
        } else {
            m = month;
            y = year;
        }
        // 修正公式:确保计算的星期符合周日为0的排版逻辑
        return (1 + 13 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
    }

    public void printMonthCalendar() {
        // 打印月份标题
        System.out.printf("       %s %d%n", MONTHS[month], year);
        // 打印星期表头
        System.out.println(" S  M  T  W  T  F  S");

        int startDow = getStartDOW();
        // 打印月份第一天前的空格
        for (int i = 0; i < startDow; i++) {
            System.out.print("   ");
        }

        int numDays = getNumDays();
        int currentDow = startDow;
        for (int day = 1; day <= numDays; day++) {
            System.out.printf("%2d ", day);
            // 周六后换行
            if (currentDow == 6) {
                System.out.println();
                currentDow = 0;
            } else {
                currentDow++;
            }
        }
        // 如果最后一行没换行,补换行
        if (currentDow != 0) {
            System.out.println();
        }
        // 月份之间空行分隔
        System.out.println();
    }

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);

        System.out.println("Enter year: ");
        int year = s.nextInt();

        // 遍历12个月,打印每个月的日历
        for (int month = 1; month <= 12; month++) {
            YearCalendar cal = new YearCalendar(month, year);
            cal.printMonthCalendar();
        }
        s.close();
    }
}

额外说明

  • 修正了getStartDOW的公式,确保计算的星期几符合周日为0的排版要求(原公式返回值偏移1)。
  • 将类名改为YearCalendar更贴合功能定位,也可以保留原Month类名。
  • 每个月日历打印后添加空行,提升可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:50:37