功能介绍:
1. 使用年、月、日构建日期
2. 对年、月、日进行了合法性检查,创建成功的日期都是合法的日期。合法性检查包括:每个月的天数、闰年(存在2月29日)、平年(不存在2月29日)
3. 返回任意日期的nextDay(带参数方法),无参方法可用于循环输出下一日
注:看似简单的一次增强,也花掉了不少时间!
运行结果示例:
d1:2018年12月31日 d2:2018年1月1日 d4:2018年2月28日 d5:1918年1月1日 d7:2019年1月1日 2018年12月31日的下一天是:2019年1月1日
2019年1月1日的下一天是:2018年1月2日
2019年2月28日的下一天是:2019年3月1日
2019年3月30日的下一天是:2019年3月31日
2019年3月31日的下一天是:2019年4月1日
2019年4月30日的下一天是:2019年5月1日
2019年6月1日的下一天是:2019年6月2日
当前日期是:2018年12月31日,之后500天分别为:
Day 1:2019年1月1日 Day 2:2019年1月2日 Day 3:2019年1月3日 …… Day 498:2020年5月12日 Day 499:2020年5月13日 Day 500:2020年5月14日
|
代码:
1. 实体类(Date)
import java.util.Calendar;
//JHTP Exercise 8.8: Enhancing Class Date
//by pandenghuang@163.com
/**
* 8.8 (Enhancing Class Date) Modify class Date of Fig. 8.7 to perform error
* checking on the initializer values for instance variables month, day and year
* (currently it validates only the month and day). Provide a method nextDay to
* increment the day by one. Write a program that tests method nextDay in a loop
* that prints the date during each iteration to illustrate that the method
* works correctly. Test the following cases: a) incrementing into the next
* month and b) incrementing into the next year.
*/
public class Date {
private static int month; // 1-12
private static int day; // 1-31 based on month
private static int year; // any year
private static final int[] daysPerMonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//constructor: confirm proper value for month and day given the year
public Date(int year, int month, int day) {
// check for year up to next year and later than 1918 //2018年12月添加
if (year < 1918 || year > Calendar.getInstance().get(Calendar.YEAR) + 100) // 获取下一年的下100年
throw new IllegalArgumentException(
"year (" + day + ") out-of-range. A year later than 1918 and up to next 100 years is expected.");
// check if month in range
if (month <= 0 || month > 12)
throw new IllegalArgumentException("month (" + month + ") must be 1-12");
// check if day in range for month
if (day <= 0 || (day > daysPerMonth[month] && !(month == 2 && day == 29)))
throw new IllegalArgumentException("day (" + day + ") out-of-range for the specified month and year");
// check for leap year if month is 2 and day is 29
// 闰年判定规则:能被400整除,或,能被4整除但不能被100整除
if (month == 2 && day == 29 && !(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))
throw new IllegalArgumentException("day (" + day + ") out-of-range for the specified month and year");
Date.month = month;
Date.day = day;
Date.year = year;
//System.out.printf( "日期对象创建成功:%s%n", this);
}
public Date() {
Date.year = Calendar.getInstance().get(Calendar.YEAR);
Date.month = Calendar.getInstance().get(Calendar.MONTH) + 1;
Date.day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
}
//return a String of the form month/day/year
public String toString() {
return String.format("%d年%d月%d日", year, month, day);
}
//增加一天,2018年12月添加
public static Date nextDay(int year, int month, int day) {
//数据校验逻辑(与构造函数相同)
// check for year up to next year and later than 1918 //2018年12月添加
if (year < 1918 || year > Calendar.getInstance().get(Calendar.YEAR) + 100) // 获取下一年的下100年
throw new IllegalArgumentException(
"year (" + day + ") out-of-range. A year later than 1918 and up to next 100 years is expected.");
// check if month in range
if (month <= 0 || month > 12)
throw new IllegalArgumentException("month (" + month + ") must be 1-12");
// check if day in range for month
if (day <= 0 || (day > daysPerMonth[month] && !(month == 2 && day == 29)))
throw new IllegalArgumentException("day (" + day + ") out-of-range for the specified month and year");
// check for leap year if month is 2 and day is 29
// 闰年判定规则:能被400整除,或,能被4整除但不能被100整除
if (month == 2 && day == 29 && !(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))
throw new IllegalArgumentException("day (" + day + ") out-of-range for the specified month and year");
switch (month) {
//1月,3月,5月,7月,8月,10月和12月为小月,每月31天
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day + 1 > 31) {
day = 1;
if (month + 1 > 12) {// 如果是12月31日,加一天后进入新的一年的第一天(元旦)
month = 1;
++year;
} else
++month;
} else
++day; // 非月末,日期直接加一
break;
//4月,6月,9月和11月为小月,每月30天
case 4:
case 6:
case 9:
case 11:
if (day + 1 > 30) {
day = 1;
month = month + 1; // 进入下一月1号
} else
++day; // 非月末,日期直接加一
break;
case 2:// 2月既不是大月,也不是小月
if (month == 2 && day == 29 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) { // 闰年,2月为29天
day = 1;
month = month + 1; // 月份前进为3月份
} else if (month == 2 && day == 28 && !(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) { // 平年,2月为28天
day = 1;
month = month + 1; // 月份前进为3月份
} else
++day; // 非月末,日期直接加一
break;
}
return new Date(year, month, day);
}
//返回当前日期的下一天,2018年12月添加
public static Date nextDay() {
int year = Date.year;
int month = Date.month;
int day = Date.day;
switch (month) {
//1月,3月,5月,7月,8月,10月和12月为小月,每月31天
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day + 1 > 31) {
day = 1;
if (month + 1 > 12) {// 如果是12月31日,加一天后进入新的一年的第一天(元旦)
month = 1;
++year;
} else
++month;
} else
++day; // 非月末,日期直接加一
break;
//4月,6月,9月和11月为小月,每月30天
case 4:
case 6:
case 9:
case 11:
if (day + 1 > 30) {
day = 1;
month = month + 1; // 进入下一月1号
} else
++day; // 非月末,日期直接加一
break;
case 2:// 2月既不是大月,也不是小月
if (month == 2 && day == 29 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) { // 闰年,2月为29天
day = 1;
month = month + 1; // 月份前进为3月份
} else if (month == 2 && day == 28 && !(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) { // 平年,2月为28天
day = 1;
month = month + 1; // 月份前进为3月份
} else
++day; // 非月末,日期直接加一
break;
}
return new Date(year, month, day);
}
} // end class Date
2. 测试类
public class DateTest {
public static void main(String[] args) {
//测试带参数构造器
System.out.printf("d1:%s%n", new Date(2018, 12, 31));
System.out.printf("d2:%s%n", new Date(2018, 1, 1));
//System.out.printf("d3:%s%n",new Date(2119, 2, 28));
System.out.printf("d4:%s%n", new Date(2018, 2, 28));
System.out.printf("d5:%s%n", new Date(1918, 1, 1));
// System.out.printf("d6:%s%n",new Date(1917,12,31));
System.out.printf("d7:%s%n", new Date(2019, 1, 1));
//测试带参数nextDay方法
System.out.printf("2018年12月31日的下一天是:%s%n%n", Date.nextDay(2018, 12, 31));
System.out.printf("2019年1月1日的下一天是:%s%n%n", Date.nextDay(2018, 1, 1));
System.out.printf("2019年2月28日的下一天是:%s%n%n", Date.nextDay(2019, 2, 28));
System.out.printf("2019年3月30日的下一天是:%s%n%n", Date.nextDay(2019, 3, 30));
System.out.printf("2019年3月31日的下一天是:%s%n%n", Date.nextDay(2019, 3, 31));
System.out.printf("2019年4月30日的下一天是:%s%n%n", Date.nextDay(2019, 4, 30));
System.out.printf("2019年6月1日的下一天是:%s%n%n", Date.nextDay(2019, 6, 1));
// 测试无参nextDay方法
Date currentDay = new Date();// 日期初始化为当前日期
System.out.printf("%n%n当前日期是:%s,之后500天分别为:%n%n", currentDay);
for (int i = 1; i <= 500; i++) {
System.out.printf("Day %d:%s%n", i,Date.nextDay()); // 打印下一天
}
}
}