一  、实现的功能

注意:此日历只能用于计算1982年10月15日以及以后的日期

1、日期 +/- 天数 = 返回日期

    (1)如果 +/- 一个负的天数的情况

    (2)如果返回日期非法

2、两个日期之间间隔的天数,日期 - 日期 = 返回的天数(返回的天数不能为负)

3、打印某年某月的日历

二、测试

1、功能测试

(1)对输入日期合法性的测试(边界值、等价类)

          1、年份是否合法

          2、月份是否合法

          3、天数是否合法

          4、年份月份天数结合是否合法

(2)对“计算某个日期加、减天数得到另一个日期”功能的测试

         1、对于普通月份加、减的测试

         2、对于平年/闰年2月份加、减的测试

         3、对于加、减一个负数,是否可以处理

         4、如果加、减上一个数,日期小于1582年10月15,是否处理

(3)对于“计算两个日期之间间隔的天数”功能的测试

         1、测试相减之后的日期是否合法

(4)对于“打印指定日期当月的日历”功能的测试(边界值、等价类)

         1、对“输入1582年10月的日历打印”的测试

         2、对“输入大于1582年10月的日历打印”的测试

         3、对“输入小于1582年10月即非法日期日历打印”的测试

2、界面测试

(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;
 }