支线任务-找到休息日
某公司软件开发工程师孙工,作息规律为上三天班,休息一天,经常不确定休息日是否周末,为此,请你开发一个程序,当孙工输入年及月,以日历方式显示对应月份的休息日,用中括号进行标记。同时,统计出本月有几天休息,轮到周末休息有几天。(注:首次休息日是 2020 年 2 月 2 日) 具体输出情况如下图所示:
首先创建View.java类用于展示提示语收集用户输入
import java.util.Scanner;
public class View {
Scanner scanner = new Scanner(System.in);
public int getYearView() {
System.out.println("请输入年:");
int year = scanner.nextInt();
return year;
}
public int getMonthView() {
System.out.println("请输入月份:");
int month = scanner.nextInt();
return month;
}
public String continueView() {
String temp = scanner.nextLine();
System.out.println(" ");
System.out.println("是否继续?是|否");
String choose = scanner.nextLine();
return choose;
}
public String continueViewLater() {
System.out.println("是否继续?是|否");
String choose = scanner.nextLine();
return choose;
}
public void welcome() {
System.out.println("欢迎使用日历标记系统!");
}
public void bye() {
System.out.println("谢谢使用,再见!");
}
public void WeekListView() {
System.out.println("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六");
}
}
Main.java主类
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Main {
private static View view = new View();
private static boolean isContinue = true;
public static void main(String[] args) throws ParseException {
view.welcome();
printCalendar();
}
public static void printCalendar() throws ParseException {
while (isContinue) {
//设定目标时间,日历上时间都是-1
int targetYear = view.getYearView();
int targetMonth = view.getMonthView()-1;
Calendar calendar = Calendar.getInstance();
//设置年月日,从1号开始打印日历
calendar.set(targetYear, targetMonth, 1);
int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
//获得今天星期几
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
//调用星期显示
view.WeekListView();
//第一天前空格
for (int i = 1; i < dayOfWeek; i++) {
//%-左对齐
System.out.printf("%-8s", " ");
}
//本月休息天数, 本月周末休息天数
int relaxDay = 0;
int relaxWeekend = 0;
for (int i = 1; i <= maxDay; i++) {
calendar.set(Calendar.DAY_OF_MONTH, i);
Date currentDate = calendar.getTime();
int currentDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
//调用判断当天是否是休息日
if (isRelax(currentDate)) {
System.out.printf("%-8s", "[" + i + "]");
relaxDay++;
//DAY_OF_WEEK = 1是周日,=7是周六
if (currentDayOfWeek == 1 || currentDayOfWeek == 7) {
relaxWeekend++;
}
} else {
System.out.printf("%-8d", i);
}
if (currentDayOfWeek == 7) {
System.out.println(" ");
}
}
System.out.println(" ");
System.out.println("本月休息天数有" + relaxDay + "天");
System.out.println("本月轮到周末休息天数有" + relaxWeekend + "天");
String choose = view.continueView();
continueView(choose);
}
}
public static void continueView(String choose) throws ParseException {
//判断是否继续
if (choose.equals("否")) {
view.bye();
isContinue = false;
}else if(choose.equals("是")) {
printCalendar();
}else{
System.out.println("你的输入有误,请选择是或者否!");
String choose2 = view.continueViewLater();
continueView(choose2);
}
}
public static boolean isRelax(Date date) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
//原始时间,从2020-02-02作为首次休息开始日
Date beginDate = format.parse("2020-02-01");
long beginTime = beginDate.getTime();
long nowTime = date.getTime();
int result = (int) ((nowTime - beginTime) / 1000 / 60 / 60 / 24);
//判断时间间隔是否为3天
if (result >= 0 && result % 4 == 1) {
return true;
}
return false;
}
}
这里isRelax方法用于判断当前日期与2020-02-02开始休息的日子相差是否隔开3天,是则返回true即作为休息日处理;
continueView方法是用于判断是否还需要继续查询新的年份月份的日历情况;
printCalendar方法则打印用户相应输入年月份的休息日日历表。
可能问题和可能改进点:
1. Calendar设置月份的时候,输入的月份应该是实际月份-1,如c.set(Calendar.MONTH, 5);表示的是6月份。
2. 国外计算星期几的习惯从星期日开始,calendar.get(Calendar.DAY_OF_WEEK) ==1 判断的是当前日期是否是星期日,而=7则是代表星期六,可自己通过例子来测试。
3. 我这里用了calendar.set(year, month, day);的方式设置日历日子,也可通过calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month); calendar.set(Calendar.DAY_OF_MONTH, day); 某种程度上增强可读性
4. 目前这个休息表针对孙工而言,扩展性在于isRelax方法和View类本身,可以通过增加用户输入判断用户最开始休息的日子,通过修改isRelax方法中的Date beginDate = format.parse("2020-02-01");即可实现扩展性,此处注意休息日期需减一带入,判断逻辑需要考虑休息当天。
5. 学习到Date, Calendar和SimpleDateFormat的简单用法,后续有机会进一步了解可查阅API文档,可学习部分。此处简单可考虑new两个Calendar直接取calendar2.getTime().getTime()具体毫秒数减去(2020-02-02)的calendar1.getTime().getTime()。