一.结构图
二.代码
package com.zhuo.base.com.zhuo.base;
import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport;
import java.util.Scanner;
public class PrintCalendar {
/*main方法*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter full year (e.g., 2012): ");//提示用户输入年份
int year = input.nextInt();
System.out.print("Enter month as a number between 1 and 12: ");//提示用户输入月份
int month = input.nextInt();
printMonth(year, month);//打印一年中某个月的日历调用
}
/*打印一年中一个月的日历方法*/
public static void printMonth(int year, int month) {
printMonthTitle(year, month);//打印日历的标题方法调用
printMonthBody(year, month);//打印日历正文方法调用
}
/*打印月份标题方法 */
public static void printMonthTitle(int year, int month) {
System.out.println(" " + getMonthName(month) + " " + year);
System.out.println(" ---------------------------");
System.out.println(" Sun Mon Tue Wed Thu Fri Sat");
}
/*获取月份的英文名称方法 */
public static String getMonthName(int month) {
String monthName = "";
switch (month) {
case 1: monthName = "January"; break;
case 2: monthName = "February"; break;
case 3: monthName = "March"; break;
case 4: monthName = "April"; break;
case 5: monthName = "May"; break;
case 6: monthName = "June"; break;
case 7: monthName = "July"; break;
case 8: monthName = "August"; break;
case 9: monthName = "September"; break;
case 10: monthName = "October"; break;
case 11: monthName = "November"; break;
case 12: monthName = "December";
}
return monthName;
}
/*打印月体方法*/
public static void printMonthBody(int year, int month) {
int startDay = getStartDay(year, month);//为每月的第一个天获取一周的开始日期方法调用
int numOfDayInMonth = getNumberOfDaysInMonth(year, month);//获取当月天数方法调用
/* 在每月第一天之前填充空间*/
int i = 0;
for (i = 0; i < startDay; i++)
System.out.print(" ");
for (i = 1; i <= numOfDayInMonth; i++) {
System.out.printf("%4d", i);
if ((i + startDay) % 7 == 0)
System.out.println();
}
System.out.println();
}
/*获取每一年每个月开始日期*/
public static int getStartDay(int year, int month) {
final int START_DAY_FOR_JAN_1_1800 = 3;
int totalNumberOfDays = getTotalNumberOfDays(year, month);//获取从1800年1月1日到每一年每个月一号总天数的方法调用
return (totalNumberOfDays + START_DAY_FOR_JAN_1_1800) % 7;//返回每一年每一个月的开始日期
}
/*获取自1800年1月1日以来的总天数的方法 */
public static int getTotalNumberOfDays(int year, int month) {
int total = 0;
/*得到从1800年1月1号到任何一年的总天数*/
for (int i = 1800; i < year; i++)
if (isLeapYear(i))
total += 366;
else
total += 365;
for (int i = 1; i < month; i++) {
total += getNumberOfDaysInMonth(year, i);//添加从一月到日历月前一个月的天数
}
return total;
}
/*获取一个月的天数的方法*/
public static int getNumberOfDaysInMonth(int year, int month) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
return 31;
else if (month == 4 || month == 6 || month == 9 || month == 11)
return 30;
else
return isLeapYear(year) ? 29 : 28;
}
/*确定是否是闰年的方法*/
public static boolean isLeapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
}
三.结果显示
Enter full year (e.g., 2012): 2021
Enter month as a number between 1 and 12: 2
February 2021
---------------------------
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28
Process finished with exit code 0
四.自顶向下的设计
先把问题拆分成两个子问题:读取用户输人和打印该月的日历。
- 使用Scanner来读取年和月份的输人。
- 打印给定月份的日历问题可以分解成两个子问题:打印日历的标题和日历的主体
- 月历的标题由三行组成:年月、虚线、每周七天的星期名称。需要通过表示月份的数字(例如:1)来确定该月的全称(例如:January)。这个步骤是由getMonthName来完成的
- 为了打印日历的主体,需要知道这个月的第一天是星期几(getStartDay),以及该月有多少天(getNumberOfDaysInMonth),例如:2013年12月有31天,2013年12月1号是星期天。
- 怎样才能知道一个月的第一天是星期几呢?有几种方法可以求得。这里采用下面的方法。假设知道1800年1月1日是星期三(START_DAY_F0R_JAN_l_1800=3),然后计算1800年1月1日和日历月份的第一天之间相差的总天数(totalNumberOfDays)。因为每个星期有7天,所以日历月份第一天的星期就是(totalNumberOfDays+START_DAY_FOR_JAN_1_1800)%7。这样getStartDay问题就可以进一步细化为getTotalNumberOfDays。
- 要计算总天数,需要知道该年是否是闰年以及每个月的天数。所以,getTotalNumberOfDays可以进一步细化成两个子问题:isLeapYear和getNumberOfDaysInMonth。
五.实现细节
方法isLeapYear(int year)可以使用下列代码实现:
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
使用下面的事实实现getTotalNumberOfDaysInMonth(intyear.intmonth)方法:
—月、三月、五月、七月、八月、十月和十二月都有31天。四月、六月、九月和十一月都有30天。二月通常有28天,但是在闰年有29天。因此,一年通常有365天,闰年有366天。
实现getTotalNumberOfDays(int year,int month)方 法:
需 要 计 算1800年1月1日和日历月份的第一天之间的总天数(totalNumberOfDays)。可以求出1800年到该日历年的总天数,然后求出该日历年中在日历月份之前的总天数。这两个总天数相加就是
totalNumberOfDays。
要打印日历体,首先在第一天之前填充一些空格,然后为每个星期打印一条线。