日期计算器
一 完成的功能
注意:此日历只能用于计算1982年10月15日以及以后的日期
1.日期+/-天数=返回日期(处理:1.如果+/-一个负的天数的情况 2.如果加之后,或减之后的日期非法)
2.两个日期之间间隔的天数,日期-日期=返回的天数(处理:返回的天数不能为负)
3.打印某年某月本月的日历(处理:1982年十月份)
二 功能分析
三 项目测试点:
功能测试:
(1)对输入日期合法性的测试--------------------边界值等价类
1.年份是否合法
2.月份是否合法
3.天数是否合法
4.年份月份天数结合是否合法
(2)对日期+天数=返回日期功能的测试
1.对于普通月份加的测试
2.测试平年/闰年2月份加减的测试
3.对于加一个负数,是否可以处理
4.如果加上一个数,日期小于1582年10月15,是否处理
(3)对日期-天数=返回日期功能的测试
1.对于普通月份减的测试
2.测试平年/闰年2月份减的测试
3.对于减一个负数,是否可以处理
4.如果减上一个数,日期小于1582年10月15,是否处理
(4)对于日期-日期=日期的功能性测试
1.测试相减之后的日期是否合法
(5)对于输入日期,打印本月日历的功能性测试-------边界值/等价类
1.测试输入1582年10月的日历打印
2.测试大于1582年10月的日历打印
3.测试小于1582年10月即非法日期日历打印的测试
界面测试:
(1)界面是否美观,清楚
(2)如果输入错误,错误提示字样是否正常输出
(3)如果输入错误,是要重新输入本次,还是要全部重新输入
四 项目源码
class Date
{
friend ostream& operator<<(ostream& os, const Date& d);
friend istream& operator>>(istream& is, Date& d);
public:
Date(int year = 1582, int month = 10, int day = 4)
{
_year = year;
_month = month;
_day = day;
}
void PrintfMonth()//打印该日期所在月份日历
{
if (_year == 1582 && _month == 10)
{
_PrintfMonthSpecial();
}
else
{
_PrintfMonth();
}
}
//d+10
Date operator+(int day)
{
Date ret(*this);
ret += day;
return ret;
}
Date operator-(int day)
{
Date ret(*this);
ret -= day;
return ret;
}
int operator-(const Date& d) //日期-日期=返回天数
{
int ret = DayNum( d);
return ret;
}
bool operator==(const Date& d)const //只要实现> ==其他的都可以全部复用
{
return _year == d._year&&_month == d._month&&_day == d._day;
}
bool operator >(const Date& d)const
{
if (_year > d._year)
{
return true;
}
else if (_year == d._year)
{
if (_month > d._month)
{
return true;
}
else if (_month == d._month)
{
if (_day > d._day)
{
return true;
}
}
return false;
}
}
bool operator<(const Date& d)const
{
return !(*this >= d);
}
bool operator >=(const Date& d)const
{
return *this > d || *this == d;
}
bool operator<=(const Date& d)const
{
return !(*this>d);
}
int judge()
{
if (_year < 1581 || _month<1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month))//GetMonthDay不一定要写在前面,和C语言不一样,类是在类里面都会找
{
return 1;
}
if (_year == 1582)
{
if (_month < 10 || _month >12)
{
return 1;
}
if (_month == 10 && (_day <15 || _day >= GetMonthDay(_year, _month)))
{
return 1;
}
}
return 0;
}
private:
Date& operator++()//前置 返回加加之后的值
{
*this += 1;
return *this;
}
//d++ d.opeartor++(&d,0)
Date operator++(int i)//后制
{
Date ret(*this);
*this += 1;
return ret;
}
int DayNum(const Date& d)
{
//int flag = 1;
//Date* max=this;
// Date* min= &d ;
//if (*this < d)
//{
// swap(max, min);
// flag = -1;
//}
//int day = 0;
//while (*min < *max)//自定义类型前置++好
//{
// ++(*min);
// ++day;
//}
//return day*flag;//判断是正数,负数。
Date max = *this;
Date min = d;
if (*this < d)
{
max = d; min = *this;
//flag = -1;
}
int day = 0;
while (min < max)
{
++min;
++day;
}
return day;
}
Date& operator+=(int day)
{
if (day<0)//处理加一个负数的情况
{
return*this -= -day;
}
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
Date& operator-=(int day)
{
if (day < 0)//处理减一个负数的情况
{
return *this += -day;
}
_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
_month = 12;
--_year;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
void _PrintfMonth()//打印某个日期当月日历
{
cout.width(5);
cout << "日";
cout.width(5);
cout << "一";
cout.width(5);
cout << "二";
cout.width(5);
cout << "三";
cout.width(5);
cout << "四";
cout.width(5);
cout << "五";
cout.width(5);
cout << "六" << endl;
int year = _year;
int month = _month;
if ((_month == 1) || (_month == 2))
{
year -= 1;
month += 12;
}
//******************以下代码只考虑1582年10月4日之后的月历打印***************
//蔡勒公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
//w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六
//y:年(年数后两位数)c:世纪-1(年数前两位数)d:日
//m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)
int c = int(year / 100);
int y = year - 100 * c;
//计算当前月份第一天为星期几,d==1
int w = y + int(y / 4) + int(c / 4) - 2 * c + (26 * (month + 1) / 10) + 1 - 1;//***一定要注意带方括号取整数的算式,要加上int的强制类型转换
w = (w % 7 + 7) % 7;//处理负数的情况
for (int i = 0; i<w; i++)//处理第一行空白处
{
cout.width(5);
cout << " ";
}
for (int i = 0; i<7 - w; i++)//处理第一行日期
{
cout.width(5);
cout << i + 1;
}
cout << endl;
int count = 0;
for (int i = 7 - w; i< GetMonthDay(_year, _month); i++)
{
cout.width(5);
cout << i + 1;
count++;
if ((count) / 7 == 1)
{
cout << endl;
count = 0;
}
}
cout << endl;
}
void _PrintfMonthSpecial()
{
cout.width(5);
cout << "日";
cout.width(5);
cout << "一";
cout.width(5);
cout << "二";
cout.width(5);
cout << "三";
cout.width(5);
cout << "四";
cout.width(5);
cout << "五";
cout.width(5);
cout << "六" << endl;
for (int i = 0; i<1; i++)//处理第一行空白处
{
cout.width(5);
cout << " ";
}
for (int i = 0; i < 6; i++)//处理第一行日期
{
if (i >= 4)
{
cout.width(5);
cout << i + 11;
}
else{
cout.width(5);
cout << i + 1;
}
}
cout << endl;
int count = 0;
for (int i = 16; i< GetMonthDay(_year, _month); i++)
{
cout.width(5);
cout << i + 1;
count++;
if ((count) / 7 == 1)
{
cout << endl;
count = 0;
}
}
cout << endl;
}
int GetMonthDay(int year, int month)
{
static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };//每次来都不动
int day = days[month];
if ((month == 2) && ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))//如果不是二月就不用走后面了
{
day += 1;
}
return day;
}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& os, const Date& d)
{
os << d._year << "-" << d._month << "-" << d._day;
return os;
}
istream& operator>>(istream&is, Date& d)
{
is >> d._year >> d._month >> d._day;
return is;
}
void menu()
{
cout << "===================欢迎使用日期计算器==================="<<endl;
cout << "============请根据如下提示输入相应编号选择功能=========="<<endl;
cout << "================1.计算此天多少天之后的日期=============="<<endl;
cout << "================2.计算此天多少天之前的日期=============="<< endl;
cout << "================3.打印两个日期中间相隔天数=============="<<endl;
cout << "================4.打印输入日期所在月的日历=============="<<endl;
cout << "========================0.退出=========================="<<endl;
}
void test()
{
menu();
int n = 1;
while (n)
{
end6:
cout << "请按键选择相应的服务:";
cin >> n;
switch (n)
{
case 1:
{
Date d1;
int n = 0;
end1:
cout << "请输入开始日期:";
cin >> d1;
int ret= d1.judge();
if (ret == 1)
{
cout << "非法日期,重新输入"<<endl;
goto end1;
}
cout << "请输入天数:";
cin >> n;
ret= (d1 + n).judge();
if (ret == 1)
{
cout << n << "天以后的日期是非法日期" << endl;
break;
}
cout << n << "天以后的日期是:" << (d1 + n) << endl;
cout << "请继续使用" << endl;
break;
}
case 2:
{
Date d2;
int n = 0;
end2:
cout << "请输入开始日期:";
cin >> d2;
int ret= d2.judge();
if (ret == 1)
{
cout << "非法日期,重新输入" << endl;
goto end2;
}
cout << "请输入天数:";
cin >> n;
ret = (d2- n).judge();//判断减之后的日期是否合法
if (ret == 1)
{
cout << n << "天以前的日期是非法日期" << endl;
break;
}
cout << n << "天以前的日期是:" << ret << endl;
cout << "请继续使用" << endl;
break;
}
case 3:
{
Date d3;
Date d4;
end3:
cout << "请输入开始日期:";
cin >> d3;
int ret= d3.judge();
if (ret == 1)
{
cout << "非法日期,重新输入" << endl;
goto end3;
}
end4:
cout << "请输入终止日期:";
cin >> d4;
ret=d4.judge();
if (ret == 1)
{
cout << "非法日期,重新输入" << endl;
goto end4;
}
cout << "两个日期之前相差:" << d4 - d3 << "天" << endl;
cout << "请继续使用" << endl;
break;
}
case 4:
{
Date d5;
end5:
cout << "请输入日期:";
cin >> d5;
int ret = d5.judge();
if (ret == 1)
{
goto end5;
}
cout << "本月的日历为:" << endl;
d5.PrintfMonth();
break;
}
case 0:
break;
default:
cout << "输入错误!" << endl;
goto end6;
}
}
}
int main()//测试用例 +一个负数
{
test();
Date d;
system("pause");
return 0;
}