1.構造図
2.コード
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);
}
}
3.結果の表示
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
4.トップダウン設計
まず、問題を2つのサブ問題に分割します。ユーザー入力の読み取りと月のカレンダーの印刷です。
- スキャナーを使用して、年と月の入力を読み取ります。
- 特定の月のカレンダーを印刷する問題は、カレンダーのタイトルとカレンダーの本体を印刷するという2つのサブ問題に分けることができます。
- 月間カレンダーのタイトルは、年と月、点線、および7つの曜日の週名の3行で構成されます。月のフルネーム(例:1月)は、月を表す数字(例:1)で決定する必要があります。このステップは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の2つのサブ問題にさらに絞り込むことができます。
5.実装の詳細
メソッドisLeapYear(int year)は、次のコードで実装できます。returnyear
%400 == 0 ||(year%4 == 0 && year%100!= 0);
次のファクトを使用してgetTotalNumberOfDaysInMonth(intyear)を実装します。.intmonth)メソッド:
-月、3月、5月、7月、8月、10月、12月は31日です。4月、6月、9月、11月は30日あります。2月は通常28日ですが、うるう年には29日あります。したがって、通常、1年は365日であり、うるう年は366日です。
getTotalNumberOfDays(int year、int month)メソッドを実装します
。1800年1月1日から暦月の最初の日までの合計日数(totalNumberOfDays)を計算する必要があります。1800年から暦年までの合計日数を検索し、次に暦年の暦月の前の合計日数を検索できます。これらの合計2日間の合計は
totalNumberOfDaysです。
カレンダーの本文を印刷するには、最初に初日の前にいくつかのスペースを入力してから、週ごとに1行を印刷します。