任务描述:
某公司软件开发工程师孙工,作息规律为上三天班,休息一天,经常不确定休 息日是否周末,为此,请你开发一个程序,当孙工输入年及月,以日历方式显示对 应月份的休息日,用中括号进行标记.同时,统计出本月有几天休息,轮到周末休 息有几天.(注:首次休息日是2020年2月2日)
输出示例:
解题思路:
从作息规律为上三天班,休息一天可以得出,孙工的休息日是以周期为4天进行循环的;
又因题中告诉了首次休息日的时间为2020年2月2日,那么我们就用该时间作为计算的参照时间;
当用户输入年份和月份后,我们创建一个日历类对象,并设置其初始时间为用户输入所在月的第一天,即1号 ;
设置好日历对象的初始值后即可对该月中的每一天进行遍历,只要这一天与参照时间2020年2月2号的间隔天数是4的倍数,即可确定这一天为休息日。
优化:
如果按照解题思路做的话,会出现当用户输入的时间在2020年2月之前时计算结果不准确的问题,这是因为我们在计算时间差的时候只考虑到了输入为首次休息日之后的时间,如果出现更早时间,则计算结果不准确。
解决办法就是利用解题相同思路,设置一个更早的休息日时间作为参照;由于Date类最早时间时从1970年1月1日开始的,所以我们可以设置最早休息日为 1970年1月5号。
实现代码:
视图类:接收用户的输入
package day01.task;
import java.util.Scanner;
/**
* @ClassName: Views
* @Auther: 戏中人
* @Date: 2020/10/12 09:52
* @Description:视图类
*/
public class Views {
Scanner input = new Scanner(System.in);
public void print() {
System.out.println("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六\n");
}
/**获取用户输入的年份
* @Param []
* @return int
*/
public int getYear() {
System.out.println("请输入年份");
String text = input.nextLine();
int year = -1;
try {
year = Integer.parseInt(text);
} catch (RuntimeException e ){
System.out.println("格式有误,请重新输入");
return getYear();
}
if (year < 0) {
System.out.println("年份不能小于0");
return getYear();
}
return year;
}
/**获取用户输入的月份
* @Param []
* @return int
*/
public int getMonth() {
System.out.println("请输入月份:");
String text = input.nextLine();
int month = -1;
try{
month = Integer.parseInt(text);
}catch (RuntimeException e){
System.out.println("格式有误,请重新输入");
return getMonth();
}
if (month < 0) {
System.out.println("月份不能小于0");
return getMonth();
}
return month;
}
}
输出打印类:输出用户的休息日表
package day01.task;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* @ClassName: PrintOffDay
* @Auther: 戏中人
* @Date: 2020/10/12 09:50
* @Description:找到休息日并打印出来
*/
public class PrintRest {
private Views v = new Views(); //视图对象
private Calendar c = Calendar.getInstance(); //日历对象
public void printRest() throws Exception {
int restTotal = 0; //本月休息日总数
int restInWeekend = 0; //本月在周末的休息日天数
int year = v.getYear(); //用户输入的年份
int month = v.getMonth() - 1; //用户输入的月份(系统从0开始)
c.set(Calendar.YEAR,year); //设置年份
c.set(Calendar.MONTH, month); //设置月份
c.set(Calendar.DAY_OF_MONTH, 1); //设置日期为当月1号
int daysOfMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH); //获得当月的最大天数
int startOfWeek = c.get(Calendar.DAY_OF_WEEK); //计算当月1号是所在周的第几天(即可推算出星期几)
int intervalDay = getIntervalDays(c); //当前日期与2020-02-02的间隔天数
v.print();
//打印本月开始的空格
for (int j = 1; j < startOfWeek; j++) {
System.out.printf("%-8s", " ");
}
for (int i = 0; i < daysOfMonth; i++) {
if (intervalDay % 4 == 0) {
System.out.printf("%-8s", "[" + c.get(Calendar.DAY_OF_MONTH) + "]");
restTotal++; //休息日总数加1
//如果休息日是在周日周六,则在周末休息日总数加1
if (c.get(Calendar.DAY_OF_WEEK) == 1 || c.get(Calendar.DAY_OF_WEEK) == 7) {
restInWeekend++;
}
} else {
System.out.printf("%-8s", c.get(Calendar.DAY_OF_MONTH));
}
//如果是在周六,则输出要换行
if (c.get(Calendar.DAY_OF_WEEK) == 7) {
System.out.println();
}
c.add(Calendar.DAY_OF_MONTH,1);
intervalDay++;
}
System.out.println();
System.out.println("本月休息天数有:" + restTotal);
System.out.println("本月轮到周末休息天数是 " + restInWeekend + "天");
}
/**计算与1970/1/5日的间隔天数
* @Param [c]
* @return int
*/
public int getIntervalDays(Calendar c) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
Date dateBegin = sdf.parse("1970-01-05"); //由首次休息日倒推出最早休息日在1970年1月5号
Date dateEnd = c.getTime(); //日历所在日期
long timeInterval = dateEnd.getTime() - dateBegin.getTime();
int intervalDays = (int) ((timeInterval) / (24 * 60 * 60 * 1000)); //间隔天数
return intervalDays;
}
}