实训目的
掌握利用API编程的方法,尽量使用类库。
实训要求
利用类库编写程序,可以输出当月的日历(包括周)
一、 思路梳理
看到实训要求后,很快有了思路:
使用Date类(
java.util.Date
而非java.sql.Date;
)的无参构造方法获取当前日期,然后使用SimpleDateFormat类自定义日期格式,即可格式化输出当前日期。
使用Calendar
对象,通过Calendar.getInstance()
,获取当前日期和时间。 然后,设置日期设置为当月的第一天,获取这一天是星期几以及当月的总天数 仿照常见日历,输出日历的表头。根据第一天是星期几,预处理出合适的空格数 最后循环输出每一天的日期,注意在适当的时候回车。
二、 简简单单写个小程序
1. 思路理顺后,很简单就写出来了下面这段代码
java
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class version0 {
public static void main(String[] args) {
// 获取当前日期
Date date = new Date();
// 设置日期格式
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//输出当前日期
System.out.println("当前日期:" + dateFormat.format(date));
// 使用Calendar类获取当前月份
Calendar calendar = Calendar.getInstance();
// 设置Calendar对象的日期为当月的第一天
calendar.set(Calendar.DAY_OF_MONTH, 1);
// 获取当月第一天是星期几
int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// 获取当月的天数
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
// 输出日历表头
System.out.println("日\t一\t二\t三\t四\t五\t六");
// 输出日历内容
for (int i = 1; i < firstDayOfWeek; i++) {
System.out.print("\t");
}
for (int day = 1; day <= daysInMonth; day++) {
System.out.print(day + "\t");
if ((firstDayOfWeek + day - 1) % 7 == 0) {
System.out.println(); // 换行
}
}
}
}
2. 运行结果
bash
当前日期:2023-11-18
日 一 二 三 四 五 六
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 29 30
3. 反思与总结
上述代码实现的功能:
- 输出当前日期
- 输出当前月的日历
待优化之处:
- 缺少异常处理
- 缺少用户交互
- 没有模块化编程:
三、 尝试进行优化
1. 增加用户交互
为了允许用户输入,首先导入Scanner
包 import java.util.Scanner;
接下来实现用户交互即可
java
// 获取用户输入的年份和月份
Scanner scanner = new Scanner(System.in);
System.out.print("请输入年份:");
int year = scanner.nextInt();
System.out.print("请输入月份:");
int month = scanner.nextInt();
对calendar
对象的年和月进行设置
java
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1); // 月份从0开始,所以要减1
输入验证
java
// 检查输入的年份和月份是否合法
if (year < 0 || month < 1 || month > 12) {
throw new IllegalArgumentException("请输入合法的年份和月份");
}
2. 增加异常处理
增加try_catch
结构即可
3. 使用模块化编程
创建一个名为 CalendarMonth
的类,用于表示一个月的日历,并将相关的逻辑封装在这个类中。这有助于提高代码的模块化和可重用性
java
class CalendarMonth {
...
}
4. 优化后代码如下:
java
import java.util.Calendar;
import java.util.Scanner;
public class version1 {
public static void main(String[] args) {
try {
// 获取用户输入的年份和月份
Scanner scanner = new Scanner(System.in);
System.out.print("请输入年份:");
int year = scanner.nextInt();
System.out.print("请输入月份:");
int month = scanner.nextInt();
// 检查输入的年份和月份是否合法
if (year < 0 || month < 1 || month > 12) {
throw new IllegalArgumentException("请输入合法的年份和月份");
}
// 创建 CalendarMonth 对象并显示日历
CalendarMonth calendarMonth = new CalendarMonth(year, month);
calendarMonth.displayCalendar();
} catch (Exception e) {
System.err.println("发生异常:" + e.getMessage());
}
}
}
class CalendarMonth {
private int year;
private int month;
public CalendarMonth(int year, int month) {
this.year = year;
this.month = month;
}
public void displayCalendar() {
// 获取指定年份和月份的第一天
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1); // 月份从0开始,所以要减1
calendar.set(Calendar.DAY_OF_MONTH, 1);
// 获取当月的天数
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
// 输出日历表头
System.out.println("日\t一\t二\t三\t四\t五\t六");
// 输出日历内容
int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
for (int i = 1; i < firstDayOfWeek; i++) {
System.out.print("\t");
}
for (int day = 1; day <= daysInMonth; day++) {
System.out.print(day + "\t");
if ((firstDayOfWeek + day - 1) % 7 == 0) {
System.out.println(); // 换行
}
}
}
}
3. 运行结果:
bash
请输入年份:2023
请输入月份:11
日 一 二 三 四 五 六
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 29 30
bash
请输入年份:2000
请输入月份:10
日 一 二 三 四 五 六
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
29 30 31
bash
请输入年份:-1
请输入月份:-1
发生异常:请输入合法的年份和月份
4. 反思与总结
在本次优化中,我们做了改进:
-
异常处理: 引入了对输入年份和月份的合法性检查,并在不合法时抛出
IllegalArgumentException
。这提高了程序的健壮性,使得用户输入不合法的情况得到更好的处理。 -
模块化: 将日历逻辑封装到了
CalendarMonth
类中,使得main
方法更为简洁,提高了代码的可读性和可维护性。 -
可读性改进: 通过引入
CalendarMonth
类,提高了代码的模块化和结构化,使得日历的显示逻辑更加清晰。 -
用户友好性: 在用户输入不合法时,输出了相应的错误信息,提高了用户友好性。
然而,我考虑做更进一步的优化:
- 更友好的界面交互: 考虑使用图形用户界面(GUI),允许用户动态地设置年份和月份。
- 丰富功能:
- 用户输入年月日,可查询这一天的详细信息
- 用户可查询当前时间的详细信息
四、使用图形用户界面(GUI)
如果你没有接触过GUI的话,这里明显超纲了,但是如果你有兴趣,不妨试着借机学习一下。
说实话,我也没有学过GUI。
但学习不就是一种不断挑战自己的过程吗?
关于GUI(图形用户界面),你可以将其想象成程序的外貌,就像一个应用的外观和操作方式。有很多现代的Java库,比如Swing或JavaFX,可以让你相对轻松地构建出漂亮且易于使用的用户界面。
在GUI方面的改进,实际上是在考虑怎样让用户与程序更亲近。如果用户界面友好、操作直观,使用起来就会更愉快。而错误信息的提示,更是在为用户提供更好的使用体验。这有点像,如果你用过一个直观的App,你就会更喜欢用它,对吧?
至于学习新技能,总是有挑战,但正是这种挑战让人变得更强大。毕竟,不会的东西,通过学习就能变成会的!学无止境,不是吗?
1. 代码
不废话,直接放代码,如下。为了方便读者阅读,我特地花了些功夫写了还算详细、规范的注释哦🫡
java
/*
* ******************************************************************************************************
* 版权所有 © 孤酒_21L 2023/11/18
_ _ ___ __ _
(_) (_) |__ \ /_ | | |
__ _ _ _ _ _ _ _ ) | | | | |
/ _ | | | | | | | | | | | | | / / | | | |
| (_| | | |_| | | | | | | |_| | / /_ | | | |____
\__, | \__,_| | | |_| \__,_| |____| |_| |______|
__/ | _/ | ______
|___/ |__/ |______|
* 作者:孤酒_21L
* 联系方式:
* QQ:2897795436
* WeChat:gujiu_21L
*
* 这是一个GUI日历应用程序,使用Swing框架创建。用户可以通过此程序显示指定年份和月份的日历,
*
* ******************************************************************************************************
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
/**
* GUI程序主类,用于显示日历的Swing应用
*/
public class GUIProgram {
public static void main(String[] args) {
// 启动Swing线程
SwingUtilities.invokeLater(() -> {
// 创建主窗口
JFrame frame = new JFrame("Calendar GUI Program");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建面板
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
// 创建年份和月份输入框,以及显示日历的按钮
JTextField yearField = new JTextField(5);
JTextField monthField = new JTextField(3);
JButton showCalendarButton = new JButton("显示日历");
// 将组件添加到面板
panel.add(new JLabel("年份: "));
panel.add(yearField);
panel.add(new JLabel("月份: "));
panel.add(monthField);
panel.add(showCalendarButton);
// 创建文本区域用于显示日历
JTextArea calendarTextArea = new JTextArea(20, 30);
JScrollPane scrollPane = new JScrollPane(calendarTextArea);
// 将面板和文本区域添加到主窗口
frame.getContentPane().add(BorderLayout.NORTH, panel);
frame.getContentPane().add(BorderLayout.CENTER, scrollPane);
// 添加按钮点击事件监听器
showCalendarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
// 验证年份和月份的合法性
int year = Integer.parseInt(yearField.getText());
int month = Integer.parseInt(monthField.getText());
if (year < 0 || month < 1 || month > 12) {
throw new IllegalArgumentException("请输入合法的年份和月份");
}
// 创建CalendarMonth对象,用于获取日历信息
CalendarMonth calendarMonth = new CalendarMonth(year, month);
// 获取日历文本并显示在文本区域
String calendarText = calendarMonth.getCalendarText();
calendarTextArea.setText(calendarText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入数字", "错误", JOptionPane.ERROR_MESSAGE);
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(frame, "请输入合法的年份和月份", "错误", JOptionPane.ERROR_MESSAGE);
}
}
});
// 设置主窗口大小并显示
frame.setSize(400, 400);
frame.setVisible(true);
});
}
}
/**
* 用于表示一个月份的日历信息类
* 作者:孤酒_21L
* 完成时间:2023年11月19日
*/
class CalendarMonth {
private int year;
private int month;
/**
* 构造函数,初始化年份和月份
*
* @param year 年份
* @param month 月份
*/
public CalendarMonth(int year, int month) {
this.year = year;
this.month = month;
}
/**
* 获取日历文本
*
* @return 包含日历信息的字符串
*/
public String getCalendarText() {
// 用于存储日历文本的StringBuilder
StringBuilder result = new StringBuilder();
// 获取指定年份和月份的第一天
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1); // 月份从0开始,所以要减1
calendar.set(Calendar.DAY_OF_MONTH, 1);
// 获取当月的天数
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
// 输出日历表头
result.append("日\t一\t二\t三\t四\t五\t六\n");
// 输出日历内容
int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
for (int i = 1; i < firstDayOfWeek; i++) {
result.append("\t");
}
for (int day = 1; day <= daysInMonth; day++) {
result.append(day).append("\t");
if ((firstDayOfWeek + day - 1) % 7 == 0) {
result.append("\n");
}
}
// 返回日历文本的字符串形式
return result.toString();
}
}
2. 运行结果:
3. 代码精讲:
如果你没有学过GUI,接下来的内容或许可以启发到你。
java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
在这里,我们导入了一些Java类,这些类将在程序中使用。javax.swing.*
中包含用于构建图形用户界面的类,java.awt.*
中包含了抽象窗口工具包的类,java.util.Calendar
是用于处理日期和时间的类。
java
public class GUIProgram {
public static void main(String[] args) {
这里定义了一个名为 GUIProgram
的公共类,其中包含一个名为 main
的方法,它是程序的入口点。
java
SwingUtilities.invokeLater(() -> {
SwingUtilities.invokeLater()
用于确保Swing组件在事件分发线程上运行。Swing组件不是线程安全的,因此它们的操作必须在事件分发线程上执行。
java
JFrame frame = new JFrame("Calendar GUI Program");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
在这里,我们创建了一个 JFrame
对象,表示图形用户界面的主窗口。设置窗口的标题为 "Calendar GUI Program",并指定在关闭窗口时应该执行的操作。
java
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
创建一个 JPanel
对象,用于容纳图形用户界面的一部分。设置布局管理器为 FlowLayout
,这样组件将按行排列。
java
JTextField yearField = new JTextField(5);
JTextField monthField = new JTextField(3);
JButton showCalendarButton = new JButton("显示日历");
创建三个图形用户界面组件:两个文本框和一个按钮。
java
panel.add(new JLabel("年份: "));
panel.add(yearField);
panel.add(new JLabel("月份: "));
panel.add(monthField);
panel.add(showCalendarButton);
将上述创建的组件添加到面板中,其中 JLabel
用于显示标签文本。
java
JTextArea calendarTextArea = new JTextArea(20, 30);
JScrollPane scrollPane = new JScrollPane(calendarTextArea);
创建一个文本区域 JTextArea
用于显示日历信息,并将其放入带有滚动条的 JScrollPane
中。
java
frame.getContentPane().add(BorderLayout.NORTH, panel);
frame.getContentPane().add(BorderLayout.CENTER, scrollPane);
将面板和带有滚动条的文本区域添加到主窗口中,使用 BorderLayout
确保它们位于主窗口的不同部分。
java
showCalendarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
为 "显示日历" 按钮添加动作监听器,指定按钮被点击时应执行的操作。
java
try {
int year = Integer.parseInt(yearField.getText());
int month = Integer.parseInt(monthField.getText());
尝试从文本框中获取输入的年份和月份,并将它们转换为整数。
java
if (year < 0 || month < 1 || month > 12) {
throw new IllegalArgumentException("请输入合法的年份和月份");
}
验证年份和月份的合法性,如果不合法则抛出异常。
java
CalendarMonth calendarMonth = new CalendarMonth(year, month);
String calendarText = calendarMonth.getCalendarText();
calendarTextArea.setText(calendarText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入数字", "错误", JOptionPane.ERROR_MESSAGE);
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(frame, "请输入合法的年份和月份", "错误", JOptionPane.ERROR_MESSAGE);
}
}
});
在按钮被点击时,执行以下操作:尝试创建 CalendarMonth
对象,获取日历文本,将文本设置到文本区域中。如果有异常,显示相应的错误消息对话框。
java
frame.setSize(400, 400);
frame.setVisible(true);
});
}
}
设置主窗口的大小为 400x400 像素,并将其显示出来。
java
class CalendarMonth {
private int year;
private int month;
public CalendarMonth(int year, int month) {
this.year = year;
this.month = month;
}
定义了一个名为 CalendarMonth
的类,用于表示一个月份的日历信息。包含了一个构造函数用于初始化年份和月份。
java
public String getCalendarText() {
StringBuilder result = new StringBuilder();
定义了一个方法 getCalendarText
,用于获取日历信息的文本形式。使用 StringBuilder
存储文本,因为它在处理大量字符串时性能更好。
java
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
创建一个 Calendar
对象,并设置为指定年份和月份的第一天。
java
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
获取当月的天数。
java
result.append("日\t一\t二\t三\t四\t五\t六\n");
添加日历表头。
java
int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
for (int i = 1; i < firstDayOfWeek; i++) {
result.append("\t");
}
确定第一天是星期几,然后添加相应的空格,以使日历正确对齐。
java
for (int day = 1; day <= daysInMonth; day++) {
result.append(day).append("\t");
if ((firstDayOfWeek + day - 1) % 7 == 0) {
result.append("\n");
}
}
添加每一天的数字,并在需要时添加换行符,以确保日历正确排列。
java
return result.toString();
}
}
最后,返回日历信息的字符串形式。
4. 反思与总结
主要有两方面的改进:
- GUI应用程序的添加
- 代码结构和注释的优化
尽管我们花了些力气,引入了GUI的设计,在用户体验上相比命令行的输入输出有了明显的改善。 但很遗憾!😞我们可以做的还有很多,在代码的编写这一方面要补个功课还有很多!
现在的程序还有哪些问题等待被解决?
-
代码仍有冗余: 在GUI程序的部分,虽然添加了GUI的代码,但是部分逻辑和注释是复制粘贴的第一个程序的,这导致了一些代码冗余。
-
异常处理过于简单: 程序在处理异常时简单地输出错误信息,但并没有提供很好的用户反馈或交互。
-
用户界面的设计较为简单: GUI程序的用户界面可以进一步优化,比如添加更多交互元素、提供更多操作选项等,以提高用户体验。
五、丰富功能
这里我们进行了功能的拓展:
- 查询具体日期的详细信息
- 查询当前日期的详细信息
这里舍弃了GUI的设计,目的在于将更多精力放到具体的逻辑实现上,而非界面的设计。
讲真的,至少我个人是不太喜欢界面的设计的,更准确的说,我能感觉到自己在这方面的优势太小了,我就一粗老爷们,没啥美感可言😅
这里没啥好说的,代码、注释自认为写的都还算规范,也没有涉及到多么不小白的知识。
相信各位读者都应该能看得懂
1. 怕大家嫌我废话多,索性就直接放代码了
java
/*
* ******************************************************************************************************
* 版权所有 © 孤酒_21L 2023/11/18
_ _ ___ __ _
(_) (_) |__ \ /_ | | |
__ _ _ _ _ _ _ _ ) | | | | |
/ _` | | | | | | | | | | | | | / / | | | |
| (_| | | |_| | | | | | | |_| | / /_ | | | |____
\__, | \__,_| | | |_| \__,_| |____| |_| |______|
__/ | _/ | ______
|___/ |__/ |______|
* 作者:孤酒_21L
* 联系方式:
* QQ:2897795436
* WeChat:gujiu_21L
*
* 这是一个日历管理程序,用于显示指定年份和月份的日历,以及查询具体日期和当前时间的信息。
* 用户可以通过输入年份和月份,查看指定月份的日历,并提供查询具体日期和当前时间的功能。
* ******************************************************************************************************
*/
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
/**
* 主程序入口,负责用户交互和整体流程控制。
*/
public class Main {
public static void main(String[] args) {
try {
// 获取用户输入的年份和月份
Scanner scanner = new Scanner(System.in);
int year, month;
// 输入年份,验证是否合法
do {
System.out.print("请输入年份:");
year = scanner.nextInt();
} while (!isValidYear(year));
// 输入月份,验证是否合法
do {
System.out.print("请输入月份:");
month = scanner.nextInt();
} while (!isValidMonth(month));
// 创建 CalendarManager 对象,处理日历逻辑
CalendarManager calendarManager = new CalendarManager(year, month);
// 输出日历
System.out.println("\n日历信息:");
calendarManager.printCalendar();
// 查询具体日期信息
int inputYear, inputMonth, inputDay;
// 输入要查询的年份,验证是否合法
do {
System.out.print("\n请输入要查询的年份:");
inputYear = scanner.nextInt();
} while (!isValidYear(inputYear));
// 输入要查询的月份,验证是否合法
do {
System.out.print("请输入要查询的月份:");
inputMonth = scanner.nextInt();
} while (!isValidMonth(inputMonth));
// 输入要查询的日期,验证是否合法
do {
System.out.print("请输入要查询的日期:");
inputDay = scanner.nextInt();
} while (!isValidDay(inputYear, inputMonth, inputDay));
calendarManager.printDateInfo(inputYear, inputMonth, inputDay);
// 查询当前时间信息
System.out.println("\n当前时间信息:");
calendarManager.printCurrentTimeInfo();
} catch (Exception e) {
System.err.println("发生异常:" + e.getMessage());
}
}
// 新增方法:验证年份是否合法
private static boolean isValidYear(int year) {
return year > 0;
}
// 新增方法:验证月份是否合法
private static boolean isValidMonth(int month) {
return month >= 1 && month <= 12;
}
// 新增方法:验证日期是否合法
private static boolean isValidDay(int year, int month, int day) {
if (isValidYear(year) && isValidMonth(month)) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1); // 月份从0开始,所以要减1
return day >= 1 && day <= calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
}
return false;
}
}
/**
* 日历管理类,负责处理日历逻辑和日期信息的查询。
*/
class CalendarManager {
private int year;
private int month;
public CalendarManager(int year, int month) {
this.year = year;
this.month = month;
}
/**
* 打印指定年份和月份的日历。
* 作者:孤酒_21L
*/
public void printCalendar() {
try {
// 获取指定年份和月份的第一天
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1); // 月份从0开始,所以要减1
calendar.set(Calendar.DAY_OF_MONTH, 1);
// 获取当月的天数
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
// 输出日历表头
System.out.println("一\t二\t三\t四\t五\t六\t日");
// 输出日历内容
int firstDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
int offset = (firstDayOfWeek - Calendar.SUNDAY + 7) % 7;
for (int i = 0; i < offset; i++) {
System.out.print("\t");
}
for (int day = 1; day <= daysInMonth; day++) {
System.out.print(day + "\t");
if ((offset + day) % 7 == 0) {
System.out.println(); // 换行
}
}
} catch (Exception e) {
System.err.println("发生异常:" + e.getMessage());
}
}
/**
* 打印指定日期的详细信息。
*/
public void printDateInfo(int inputYear, int inputMonth, int inputDay) {
try {
// 构造用户输入的日期
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date inputDate = dateFormat.parse(inputYear + "-" + inputMonth + "-" + inputDay);
// 查询日期信息
Calendar calendar = Calendar.getInstance();
calendar.setTime(inputDate);
System.out.println("日期信息:");
// 是否为闰年
System.out.println(inputYear + " 年 " + (isLeapYear(calendar) ? "是" : "不是") + " 闰年");
// 星期几和所在周
System.out.println("这一天是" + inputYear + " 年 " + (inputMonth + 1) + " 月 的 第 " + getWeekOfMonth(calendar) + " 个 " + getDayOfWeek(calendar));
System.out.println("这一天是" + inputYear + " 年 的 第 " + getWeekOfYear(calendar) + " 个 " + getDayOfWeek(calendar));
// 当前月份和天数
System.out.println(inputYear + " 年 " + (inputMonth + 1) + " 月 " + "的 第 " + calendar.get(Calendar.DAY_OF_MONTH) + " 天");
// 当前年份和天数
System.out.println(inputYear + " 年 的 第 " + calendar.get(Calendar.DAY_OF_YEAR) + " 天");
// 距离下一年还有多少天
System.out.println("距离下一年还有" + daysUntilNextYear(calendar) + "天");
// 当前月份和年份的天数
System.out.println("当前月有" + calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + "天");
System.out.println("当前年有" + calendar.getActualMaximum(Calendar.DAY_OF_YEAR) + "天");
} catch (ParseException e) {
System.err.println("日期解析错误:" + e.getMessage());
}
}
/**
* 获取本年的第几周。
*/
private int getWeekOfYear(Calendar calendar) {
calendar.setFirstDayOfWeek(Calendar.MONDAY);
return calendar.get(Calendar.WEEK_OF_YEAR);
}
/**
* 判断是否为闰年。
*/
private boolean isLeapYear(Calendar calendar) {
int year = calendar.get(Calendar.YEAR);
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
/**
* 获取日期所在星期的名称。
*/
private String getDayOfWeek(Calendar calendar) {
String[] daysOfWeek = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" , "星期日"};
int dayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY + 7) % 7;
return daysOfWeek[dayOfWeek];
}
/**
* 获取日期所在月份的第几周。
*/
private int getWeekOfMonth(Calendar calendar) {
return calendar.get(Calendar.WEEK_OF_MONTH);
}
/**
* 获取距离下一年还有多少天。
*/
private int daysUntilNextYear(Calendar calendar) {
int currentDayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
int daysInYear = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
return daysInYear - currentDayOfYear;
}
/**
* 打印当前时间的信息。
*/
public void printCurrentTimeInfo() {
try {
// 获取当前时间信息
Calendar calendar = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = dateFormat.format(calendar.getTime());
System.out.println("当前时间:" + currentTime);
// 获取当前年
int year = calendar.get(Calendar.YEAR);
// 获取当前月
int month = calendar.get(Calendar.MONTH) + 1;
// 获取当前日
int day = calendar.get(Calendar.DATE);
System.out.println("\n当前日期信息:");
printDateInfo(year, month, day);
} catch (Exception e) {
System.err.println("发生异常:" + e.getMessage());
}
}
}
2. 运行结果
bash
请输入年份:2023
请输入月份:11
日历信息:
一 二 三 四 五 六 日
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 29 30
请输入要查询的年份:2023
请输入要查询的月份:11
请输入要查询的日期:11
日期信息:
2023 年 不是 闰年
这一天是2023 年 12 月 的 第 2 个 星期日
这一天是2023 年 的 第 46 个 星期日
2023 年 12 月 的 第 11 天
2023 年 的 第 315 天
距离下一年还有50天
当前月有30天
当前年有365天
当前时间信息:
当前时间:2023-11-19 16:26:32
当前日期信息:
日期信息:
2023 年 不是 闰年
这一天是2023 年 12 月 的 第 4 个 星期一
这一天是2023 年 的 第 47 个 星期一
2023 年 12 月 的 第 19 天
2023 年 的 第 323 天
距离下一年还有42天
当前月有30天
当前年有365天
3. 反思与总结
这次的改进主要体现在功能的丰富、逻辑的优化。
- 功能增强: 通过增加对日期的详细查询功能,程序变得更加全面。
- 用户交互改进: 使用循环确保用户输入的合法性,提高了程序的健壮性。
- 日期处理: 这次的改进增加了对日期信息的处理,高了程序的实用价值。
==可以考虑继续优化==
- 错误处理和反馈: 进一步改进错误处理机制,为用户提供清晰的错误信息和建议,以改善用户体验。
- 模块化设计: 将程序分解为更小的、相互独立的模块或类,以提高可读性、可维护性和代码复用性。
- 日历功能扩展: 添加更多的日历功能,例如显示农历、节假日、提醒功能等,提高程序的实用性。
复盘与思考
写一个程序不容易,写一个好的程序更不容易。
尽管这只是单文件的编写,代码的长度甚至一度达不到300行。。。
我们从最初的代码(version0.java
)不断迭代: version1.java
、GUIProgram.java
、Main.java
。。。
我们对程序的迭代与优化主要考虑了以下4个个方面:
- 用户交互改进
- 异常处理
- 模块化编程
- 代码的可读性
- 功能的丰富
为此我们分别做出了以下措施:
- 用户交互改进
- 允许用户输入数据
- 循环进行输入验证
- 尝试使用GUI设计
- 文本拼接
- 异常处理
- 增加
try_catch
结构
- 增加
- 模块化编程
- 将程序分解为更小的、相互独立的模块或类
- 代码的可读性
- 增加版权声明
- 文档注释,如@return 等
- 变量、方法等采用驼峰式命名
- 功能的丰富
- 尝试实现日历动态查询
- 尝试实现日期的详细信息输出
我必须承认我在程序的设计和编写上有诸多不足!
-
设计上的缺陷: 在程序的设计上,最初的版本 (
version0.java
) 显然过于简单,仅仅是一个基本的输出日历的功能。虽然后续版本加入了用户输入验证、异常处理、GUI设计等功能,但最初的设计没有考虑到程序可能需要的扩展性和复杂性。在一开始,对于如何更好地组织代码和构建模块化的结构缺乏深思熟虑。 -
缺乏面向对象的思考: 初期的版本较为过程化,没有充分运用面向对象的设计原则。在
version1.java
中,虽然引入了CalendarManager
类,但整体设计还是偏向过程化的风格。面向对象的思考可以更好地体现在类的设计和交互上,提高代码的可维护性和可扩展性。 -
代码重复问题: 在不同版本中,存在一些代码重复的情况,例如输入验证部分。尽管在后续版本中有所改进,但依然可以进一步提高代码的重用性。
-
GUI设计的深度不足: 在尝试实现GUI 版本时 (
GUIProgram.java
),尽管成功使用了Swing 框架,但整体的GUI设计仍显得相对简单。深度的不足主要体现在对布局管理器的选择上,也没有充分考虑用户体验和界面的美观性。GUI设计是一个庞大的领域,显然我还需要更深入的学习和实践。 -
不足的异常处理: 尽管在后续版本(自
version1.java
)中加入了异常处理机制,但在一些情况下,错误处理仍显得不够全面。对于用户输入的异常情况,程序不能够提供足够的友好提示。 -
对于日历和日期处理的局限性: 程序中的日历和日期处理逻辑还有一些局限性。例如,在处理星期几和周数时,可能需要更全面的考虑。对于日期的详细信息输出,虽然有所增加,但仍可以进一步扩展,加入更多的相关信息。
-
缺乏整体规划: 在整个设计和迭代的过程中,缺乏整体规划和设计的思考。每个版本的迭代相对独立,没有清晰的长期目标和蓝图。更好的方式可能是需要在一开始就规划好整个项目的结构和功能。
不行,净整自我批判了,再批判我就遭不住了😭,我得夸夸自己哈哈
当然要夸夸自己啦!哈哈哈。
毕竟辛辛苦苦写出来的东西,得给自己点个赞👍才对嘛。
你看咱这不也挺厉害的吗?程序一点点往前改,一点点长大,简直就是个小可爱成长记。尤其是GUI那一块,用Swing搞定,现在回过头看看,我都想给自己鼓个掌👏👏👏了。
有时候搞代码就是这样,一开始可能啥都不懂,写点啥都觉得自己要牛逼上天了。然后才慢慢发现,"哎呀🤨,这地方能再优化一下",然后再优化,再优化,优化到我都看不下去了🤣。但最终的成果看上去是不是舒服多了?
而且,从命令行版到GUI,再到各种功能的加强,这不是一点点的进步,是突飞猛进啊。🤔
代码的可读性和注释也越来越走心了,这可是让别人看懂咱代码的重要一环。写注释就像跟代码聊天,告诉它:"老铁,这里是干嘛的,不要搞错喽。"🤟
总之,干的还不错,程序也长得越来越像个样子了。继续保持这个学习和进步的态度,下一个项目还能更出彩!💪😄
自夸严肃版
- 学习态度积极: 从一开始程序的简单编写,再到挑战 GUI 编程。
- 代码迭代优化: 通过不断的迭代和优化,程序逐渐完善,从命令行版到 GUI,再到功能的丰富,展现了很好的进步。
- 挑战 GUI 设计: 使用 Swing 框架设计 GUI 界面,这可是不少初学者望尘莫及的领域。这方面的尝试和实践很值得称赞。
- 注释和可读性: 注释内容丰富有趣,既解释了代码,又融入了一些趣味小知识,这对于提高代码可读性和吸引读者注意是很好的尝试。
- 逻辑思维逐渐清晰: 通过不断改进代码,逻辑结构变得更加清晰,程序的整体架构也更加合理。
- 对异常处理的考虑: 引入了异常处理机制,对用户的输入进行了合法性验证,提高了程序的健壮性。
各位!大家好,我叫 孤酒_21L , 一个普普通通的大学生 。 我的最终目标是写出既优雅又高效的代码。💪 各位!我们砥砺前行,未来可期!🚀😄