Java程序设计课程中有一个练习任务:在控制台输出指定年月的月历。完成任务的一个要点是获取指定年月的1号是周几。老师给的实现案例里用的是Calendar类的get方法。一个学生自己想了别的办法实现——自己指定一个日期作为参考点,计算1号到这个参考点间隔的天数,从而推算出1号是周几。并且将实现代码封装成了类,提供了多种构造方法,包括用字符串参数构建Calendar对象,通过正则表达式解析字符串,得到年月日。
通过这个练习,反映了该同学主动学习、主动思考、愿意创新的学习态度。不机械的照抄老师给的答案,能想出新的思路,灵活运用自己学到的知识,解决实际问题。这才是大学生该有的学习态度。
编程不是背书,而是用编程语言表达自己的思想。所以,你得有思想、有想法、有思路、会表达。平时这样练习多了,慢慢就会了。不愿意思考,不愿意实践是学不好编程的。
下面是该同学的代码原样。
package org.example;
import java.time.LocalDate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MonthlyCalendar {
// 成员属性
// 定义判断标准(周一),日期比对全部以此为标准
private static final LocalDate DEFAULT_DATE = LocalDate.of(2024, 1, 1);
// 定义列表,存储每个月包含的天数
int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 定义当前时间
// 无参传递,默认为当前时间
private LocalDate usertime=LocalDate.now();
// 构造函数
public MonthlyCalendar() {
// 无参传递,默认为当前时间
printCalendar();
}
public MonthlyCalendar(String s){
// 有参传递,用正则分割日期
Pattern p = Pattern.compile("(\\d{4})-(\\d{1,2})-(\\d{1,2})");
Matcher m = p.matcher(s);
if (m.find()){
// System.out.println(m.group(1)+"\t"+m.group(2)+"\t"+m.group(3));
// 因为修改日会重置月,所以月份最后修改
usertime = usertime.withDayOfYear(Integer.parseInt(m.group(3)));
usertime = usertime.withYear(Integer.parseInt(m.group(1)));
usertime = usertime.withMonth(Integer.parseInt(m.group(2)));
// System.out.println(usertime);
printCalendar();
}else {
System.out.println("时间格式有误");
}
}
// 成员方法
// 打印界面
private void printCalendar() {
System.out.println("\n\n\n\n\n时间:"+usertime);
// 调用函数获取周值
int startdate = dateDifferent();
// 判断是否为周日,是的话重置循环次数来确保打印列表周日在前
startdate = startdate == 7 ? 0 : startdate;
// 根据当前年份决定2月多少天
days[1] = leapYear(usertime.getYear()) ? 29 : 28;
// 定义计数器,用于判断换行
int count = 0;
System.out.println("\n日\t\t一\t\t二\t\t三\t\t四\t\t五\t\t六");
for (int i = 0; i < startdate; i++) {
System.out.printf("--\t\t");
count++;
}
for (int i = 1; i < days[usertime.getMonthValue() - 1] + 1; i++) {
System.out.printf(i + "\t\t");
count++;
if (count % 7 == 0) {
System.out.println();
}
}
}
// 获取时间差
private int dateDifferent() {
// 定义开始与结束年月单独存储变量
int sy, sm, ey, em;
// 定义存储用户时间在前(决定星期值返回顺序)
boolean isbig;
// 判断用户时间位置,true:在前,false:在后
if (usertime.isBefore(DEFAULT_DATE)) {
isbig = false;
System.out.println("用户时间在前");
sy = usertime.getYear();
sm = usertime.getMonthValue();
ey = DEFAULT_DATE.getYear();
em = DEFAULT_DATE.getMonthValue();
} else {
isbig = true;
System.out.println("用户时间在后");
sy = DEFAULT_DATE.getYear();
sm = DEFAULT_DATE.getMonthValue();
ey = usertime.getYear();
em = usertime.getMonthValue();
}
// 判断年与年之间相差天数
System.out.println("起始年:" + sy + "\t结束年:" + ey);
int yearstodays = 0;
for (int i = sy; i < ey; i++) {
yearstodays += leapYear(i) ? 366 : 365;
}
System.out.println("两年相差天数:" + yearstodays);
// 计算起始年与结束年多余月的天数
System.out.println("起始月:" + sm + "\t\t结束月:" + em);
int usedate = 0, nusedate = 0;
days[1] = leapYear(sy) ? 29 : 28;
for (int i = 0; i < sm - 1; i++) {
usedate += days[i];
}
days[1] = leapYear(ey) ? 29 : 28;
for (int i = 0; i < em - 1; i++) {
nusedate += days[i];
}
System.out.println("起始月天数:" + usedate + "\t结束月天数:" + nusedate);
// 期间时间=两年之间日期-起始年已用日期+结束年未用日期
int endate = yearstodays - usedate + nusedate;
System.out.println("两日期相差天数为:" + endate);
// 返回当月第一天是周几,根据用户时间与基准时间的位置取不同值
// 前者为用户时间在后,正常返回值
// 后者为用户时间在前,需要返回7-时间,但是因为未知原因,老是少两天,所以直接返回9-时间解决bug
return isbig ? endate % 7 + 1 : 9 - (endate % 7 + 1);
}
// 判断是否闰年(true:是,false:否)
private boolean leapYear(int n) {
return (n % 4 == 0 && n % 100 != 0) || n % 400 == 0;
}
}
package org.example;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// System.out.println("请输入一个日期,格式为yyyy-mm-dd:");
// String date = input.nextLine();
// 有参调用,以当前时间为主
MonthlyCalendar yl = new MonthlyCalendar("2024-6-1");
// 无参调用,以系统时间为主
MonthlyCalendar yl2 = new MonthlyCalendar();
}
}