Java基础小练习——万年历

一、代码运行截图

1.1 开始欢迎页面

  • 提示输入年份和月份

1.2 展示日历页面

  • 展示对应年月的日历,并继续提醒是否继续查找

1.3 继续输入页面

1.4 退出页面

二、实现思路

  • 考虑不同情况

    • 是否为闰年

    • 每月的天数

    • 周日-周六如何对应具体日期

  • 当前年月日距离1900年1月1日间隔天数

    • 同年同月不同日间隔(3月5日~3月20日):20-15=5天

    • 间隔天数 = 终止日期 - 起始天数

    • 需要:1月1日~1月15日

    • 间隔天数 = 终止日期

    • 同年不同月不同日间隔(1月15日~10月3日):(31-15) + 28/29 +31+30+31+30+31+31+30 + 3 = 242天 / 243天

    • 间隔天数 = (起始月总天数 - 起始日期) + 对应月份的天数 * (起始月份-1 ~ 终止月份-1)月 + 终止日期

    • 需要:1月1日~10月3日

    • 间隔天数 = 1~9月整月天数 + 终止日期

    • 不同年不同月不同日间隔(1900年1月1日~2025年10月3日):

    • 计算思路:1900年1月1日 —> 2025年1月1日 —> 2025年10月3日

    • 计算间隔年份 = 终止年 - 1900

    • 计算整年天数间隔天数:可以不同完整算出来,使用while遍历即可,算出整年天数

    • 计算不同月不同日间隔天数:1~终止月整月天数 + 终止日期

    • 间隔天数 = 间隔年份 *对应年份天数 + 1~终止月整月天数 + 终止日期

三、总结

0、界面撰写

  • 开始页面

  • 继续查找月份页面

  • 结束页面

  • 注意输入异常的判断

1、输出的日历格式(important!!!)

  • 标头的构造

  • 先找到当月第一天为周几

  • 再打印一开始的,空白部分

  • 从1号开始遍历整个月,按照一定规律输出

  • 遇到周六时,换行

2、计算间隔天数

  • 计算间隔整年,并注意是否是不是闰年

  • 计算整月月数

  • 计算最后一个月的天数:注意:如果是1号,那也算一天,因此是 目标日期 - 1

3、闰年计算

  • 能被4整除,但不能被100整除的是闰年

  • 能被400整除的是闰年

4、封装一个输入年月的类

  • 创建一个新类YearMonth,变量为year和month,并创建全参构造函数

  • 在万年历的类中,创建一个新的方法,用于接收输入的年和月,这样可以把在【开始页面】和【继续查找】页面上,直接新建一个YearMonth,去调用方法,即可同时返回年和月的数据

5、退出逻辑优化

  • 将Calendar中的循环判断去除,放到welcome的页面中

  • 创建一个boolean类型的标识符flag,默认为true(第一次默认出现是否查看),进行查看,并在输出当月的日历后,让用户做出判断,y继续,flag仍然为true,否则flag为false,跳出循环,程序结束

四、源代码
 

package com.yeban.base.Test;

import java.util.Scanner;

/**
 * @Desc TODO
 * @Author yeban
 * @Date 2025/10/2
 */
// 万年历
public class PerpetualCalendar {

    public void welcome() {

        Scanner sc = new Scanner(System.in);
        System.out.println("*-----------------欢迎使用万年历-----------------*");

        boolean flag = true;
        while(flag) {
            // 判断是否继续查看万年历
            System.out.println("请输入年份(1900以后):");
            int year = sc.nextInt();
            System.out.println("请输入月份:");
            int month = sc.nextInt();
            Calendar(year,month);
            flag = next();
        }

    }

    // 是否继续页面
    public boolean next() {
        Scanner sc = new Scanner(System.in);
        System.out.println("------------继续---Y|y    退出----N|n------------");
        String select = sc.next();
        switch (select) {
            case "Y":
            case "y":
                return true;
            case "N":
            case "n":
                System.out.println("---------------感谢使用万年历!!!!---------------");
                return false;
            default:
                System.out.println("输入选项错误!请重新输入!");
                return next();
        }
    }

    // important!!
    // 显示月份,日期,星期:1900年1月1日 是 星期一
    public void Calendar(int year, int month) {
        System.out.print("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六");
        System.out.println();

        int days = daysOfMonth(year,month); //当月天数
        int firstDayOffset = apartDays(year,month,1);    // 当月第一天距离1900年1月1日的天数
        int firstIndex = (firstDayOffset + 1) % 7;     // 计算是星期几
        
        // 打印空格
        for(int i = 0; i < firstIndex; i++) {
            System.out.print("\t\t");
        }

        // 打印日期
        for(int i = 1; i <= days; i++) {
            System.out.print(i + "\t\t");
            if((i + firstIndex) % 7 == 0) { // 星期六就换行
                System.out.println();
            }
        }
        System.out.println();

    }

    // 目标日期与1900年1月1日相隔天数半段
    public int apartDays(int year, int month, int day) {
        // 相隔多少天,差几月,差几年
        int days = 0;
        int months = month - 1;

        // 加整年间隔天数
        for (int y = 1900; y < year; y++) {
            days += isLeapYear(y) ? 366 : 365;
        }

        // 加差整月的天数
        while(months != 0) {
            days += daysOfMonth(year,months);
            months --;
        }

        // 加最后一个月的天数,并返回
        return days + day - 1;
    }

    // 判断闰年
    public boolean isLeapYear(int year) {
        // 闰年能被4整除,但不能被100整除
        // 或者能被400整除的年份是闰年
        if ( (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) ) {
            return true;
        }
        return false;
    }

    // 判断月份对应的天数
    public int daysOfMonth(int year, int month) {

        int days = 0;

        switch (month) {
            // 一个月31天的月份
            case 1:     // January (一月)
            case 3:     // March (三月)
            case 5:     // May (五月)
            case 7:     // July (七月)
            case 8:     // August (八月)
            case 10:    // October (十月)
            case 12:    // December (十二月)
                days = 31;
                break;

            // 一个月30天的月份
            case 4:     // April (四月)
            case 6:     // June (六月)
            case 9:     // September (九月)
            case 11:    // November (十一月)
                days = 30;
                break;

            // 特殊的二月
            case 2: // February (二月)
                if(isLeapYear(year)) {
                    days = 29;
                    break;
                } else {
                    days = 28;
                    break;
                }

            // 用户输入错误
            default:
                System.out.println("输入的月份有误!请重新输入!");
        }

        return days;
    }

    public static void main(String[] args) {

        PerpetualCalendar c = new PerpetualCalendar();

        // 进入欢迎界面
        c.welcome();

    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值