QUESTION
package net.mooctest;
public class Date {
private Day d;
private Month m;
private Year y;
public Date(int pMonth, int pDay, int pYear) {
y = new Year(pYear);
m = new Month(pMonth, y);
d = new Day(pDay, m);
}
public void increment() {
if (!d.increment()) {
if (!m.increment()) {
y.increment();
m.setMonth(1, y);
}
d.setDay(1, m);
}
}
public void printDate() {
System.out.println(m.getMonth() + "/" + d.getDay() + "/" + y.getYear());
}
public Day getDay() {
return d;
}
public Month getMonth() {
return m;
}
public Year getYear() {
return y;
}
public boolean equals(Object o) {
if (o instanceof Date) {
if (this.y.equals(((Date) o).y) && this.m.equals(((Date) o).m)
&& this.d.equals(((Date) o).d))
return true;
}
return false;
}
public String toString() {
return (m.getMonth() + "/" + d.getDay() + "/" + y.getYear());
}
}
package net.mooctest;
public class Month extends CalendarUnit {
private Year y;
private int[] sizeIndex = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
public Month(int pMonth, Year y) {
setMonth(pMonth, y);
}
public void setMonth(int pMonth, Year y) {
setCurrentPos(pMonth);
this.y = y;
if (!this.isValid()) {
throw new IllegalArgumentException("Not a valid month");
}
}
public int getMonth() {
return currentPos;
}
public int getMonthSize() {
if (y.isLeap())
sizeIndex[1] = 29;
else
sizeIndex[1] = 28;
return sizeIndex[currentPos - 1];
}
public boolean increment() {
currentPos += 1;
if (currentPos > 12)
return false;
else
return true;
}
public boolean isValid() {
if (y != null && y.isValid())
if (this.currentPos >= 1 && this.currentPos <= 12)
return true;
return false;
}
public boolean equals(Object o) {
if (o instanceof Month) {
if (this.currentPos == ((Month) o).currentPos
&& this.y.equals(((Month) o).y))
return true;
}
return false;
}
}
package net.mooctest;
public class Year extends CalendarUnit {
public Year(int pYear) {
setYear(pYear);
}
public void setYear(int pYear) {
setCurrentPos(pYear);
if (!this.isValid()) {
throw new IllegalArgumentException("Not a valid month");
}
}
public int getYear() {
return currentPos;
}
public boolean increment() {
currentPos = currentPos + 1;
if (currentPos == 0)
currentPos = 1;
return true;
}
public boolean isLeap() {
if (currentPos >= 0
&& (((currentPos % 4 == 0) && (currentPos % 100 != 0)) || (currentPos % 400 == 0)))
return true;
else if (currentPos < 0
&& ((((currentPos * -1) % 4 == 1) && ((currentPos * -1) % 100 != 1)) || ((currentPos * -1) % 400 == 1)))
return true;
return false;
}
protected boolean isValid() {
if (this.currentPos != 0)
return true;
return false;
}
public boolean equals(Object o) {
if (o instanceof Year) {
if (this.currentPos == ((Year) o).currentPos)
return true;
}
return false;
}
}
package net.mooctest;
public abstract class CalendarUnit {
protected int currentPos;
protected void setCurrentPos(int pCurrentPos) {
currentPos = pCurrentPos;
}
protected int getCurrentPos() {
return currentPos;
}
protected abstract boolean increment();
protected abstract boolean isValid();
}
package net.mooctest;
public class Nextday {
public static Date nextDay(Date d) {
Date dd = new Date(d.getMonth().getCurrentPos(), d.getDay().getCurrentPos(), d.getYear().getCurrentPos());
dd.increment();
return dd;
}
}
ANSWER ()
package net.mooctest;
import static org.junit.Assert.*;
import org.junit.Test;
//我习惯从功能分析,次日函数是干嘛的,是输入今天告诉我明天。
//所以我们需要考虑今天到明天的日期变化。
public class NextdayTest {
@Test
public void testValid() {
Nextday n = new Nextday();
//首先是最简单的只增长date,我们可以随意挑选一个日期,
//验证次日函数给我们的结果是否和已知的次日日期相同:
Date currentday=new Date(2,22,2023);
Date nextday=Nextday.nextDay(currentday);
Date expectday=new Date(2,23,2023);
assertEquals(expectday,nextday);
//然后考虑date满了进到月份,相同的方法去验证:
currentday=new Date(1,31,2023);
nextday=Nextday.nextDay(currentday);
expectday=new Date(2,1,2023);
assertEquals(expectday,nextday);
//如果说月份也满了,就要加年份
currentday=new Date(12,31,2022);
nextday=Nextday.nextDay(currentday);
expectday=new Date(1,1,2023);
assertEquals(expectday,nextday);
//这些都是理所应当一定会发生的,非常好想
//然后我们需要考虑一些奇奇怪怪的日子
//首先能想到就是2月的分界点28、29
//注意我们这里都是先讨论的可以发生的情况,像5201314月10086日这种日子我们先不管他
currentday=new Date(2,28,2020);
nextday=Nextday.nextDay(currentday);
expectday=new Date(2,29,2020);
assertEquals(expectday,nextday);
currentday=new Date(2,27,2023);
nextday=Nextday.nextDay(currentday);
expectday=new Date(2,28,2023);
assertEquals(expectday,nextday);
//因为题目中有
//else if (currentPos < 0 && ((((currentPos * -1) % 4 == 1) &&
//((currentPos * -1) % 100 != 1)) || ((currentPos * -1) % 400 == 1)))
// return true;
//这样的判断,所以年份可能会是个负数
currentday=new Date(2,28,-2017);
nextday=Nextday.nextDay(currentday);
expectday=new Date(2,29,-2017);
assertEquals(expectday,nextday);
currentday=new Date(2,28,-2018);
nextday=Nextday.nextDay(currentday);
expectday=new Date(3,1,-2018);
assertEquals(expectday,nextday);
//-2017和-2018覆盖了
//&& ((((currentPos * -1) % 4 == 1) && ((currentPos * -1) % 100 != 1)) ||((currentPos
//-1) % 400 == 1)))
// return true;
//这条语句
currentday=new Date(12,31,-1);
nextday=Nextday.nextDay(currentday);
expectday=new Date(1,1,1);
assertEquals(expectday,nextday);
currentday.printDate();
currentday.toString();
//接下来对day-month-year(12,31,-1)的功能分析
assertEquals(31,currentday.getDay().getDay());
assertEquals(12,currentday.getMonth().getMonth());
assertEquals(-1,currentday.getYear().getYear());
Year y1=new Year(1111);
Month m1=new Month(11,y1);
Day d1=new Day(20,m1);
//这里就是搞一个新日期和刚刚的日期比较年月日是否相等
//这样get.get和get.equal就覆盖了
assertEquals(false,currentday.getDay().equals(d1));
assertEquals(false,currentday.getMonth().equals(m1));
assertEquals(false,currentday.getYear().equals(y1));
assertEquals(false,currentday.getYear().equals(m1));
assertEquals(false,currentday.getMonth().equals(y1));
assertEquals(false,currentday.getDay().equals(m1));
assertEquals(false,currentday.equals(y1));
y1=new Year(-1);
m1=new Month(12,y1);
d1=new Day(31,m1);
//false有了,那就要搞一些true的测试
assertEquals(true,currentday.getDay().equals(d1));
assertEquals(true,currentday.getMonth().equals(m1));
assertEquals(true,currentday.getYear().equals(y1));
//currentday.equal也要覆盖,然后注意false&true
currentday=new Date(2,22,2023);
nextday=new Date(2,22,2023);
assertEquals(true,currentday.equals(nextday));
nextday=new Date(2,23,2023);
assertEquals(false,currentday.equals(nextday));
}
//下面来解决边界溢出的日期
//日期大于31
@Test(expected=IllegalArgumentException.class)
public void testInvalidDay() {
Year y=new Year(2023);
Month m=new Month(11,y);
Day d=new Day(32,m);
}
//月份为null
@Test(expected=IllegalArgumentException.class)
public void testInvalidMonth1() {
Day d=new Day(2,null);
}
//月份超过12
@Test(expected=IllegalArgumentException.class)
public void testInvalidMonth2() {
//月份超过12
Year y=new Year(2023);
Month m=new Month(13,y);
}
//年份null
@Test(expected=IllegalArgumentException.class)
public void testInvalidYear1() {
Year y=null;
Month m=new Month(1,y);
}
//年份为0
@Test(expected=IllegalArgumentException.class)
public void testInvalidYear2() {
Year y=new Year(0);
}
}
RESULT