C++日期类Date的实现

来源:互联网 发布:纽约客插画知乎 编辑:程序博客网 时间:2024/04/28 00:29

在学C++类的时候,日期类是一个很基础也很重要的类,所以有必要实现一下。

常规日期类的本身并不复杂,实现的过程主要涉及到了一些构造函数,拷贝构造函数,以及各种运算符的重载等,而难点主要在于如何保证日期的有效性,比如我们知道年必须为正数,月都是1-12之间的整数,各个月的天数不同以及闰年2月天数的变化等等,如何将这些体现在我们对于一个日期类对象进行自增,自减以及加减多少天得出正确的日期等运算中。

下面先给出类的定义:

class Date {friend ostream& operator<<(ostream& _cout, const Date& date);friend istream& operator>>(istream& _cin, Date& date);public:Date(int year = 1990, int month = 1, int day = 1);Date(const Date& date);Date& operator=(const Date& date);Date operator+(int day);Date& operator++();Date operator++(int);Date operator-(int day);int operator-(const Date& date);Date& operator--();Date operator--(int);bool operator>(const Date& date);bool operator<(const Date& date);bool operator==(const Date& date);bool operator!=(const Date& date);bool operator>=(const Date& date);bool operator<=(const Date& date);private:bool IsLeapYear(int year){return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);}int GetDaysInMonth(int year, int month){int months[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (IsLeapYear(year)) {months[2] = 29;}return months[month];}private:int _year;int _month;int _day;};


类的具体实现中,其他都比较简单不多说,我们主要看看关于以下函数的实现过程

Date date(2016, 10, 17);

Date date2(2017, 3, 1);

date++;

++date;

date = date + 100;

date = date - 100;

int days = date2 - date1;


在这里,我是先进行Date operator+(int day)的具体实现,然后对于date++这种实现中直接调用date+1,且保证date=date+1。

当然也可以先进行自增++的重载,然后date+day的时候写个循环调用自增运算,只不过需要创建一个临时对象,记得保留原来的值即可。

具体原理如下:

对于2016.10.17比如说我们要看100天后的日期是哪一天,我们不妨直接先加,得出2016.10.117,显然这个日期的日并不合法,因此我们进行改变。

考虑到10月有31天,我们对日期的天进行减31天,得到2016.11.86,依旧不合法,我们继续改变,考虑到11月有30天,我们减后到得到2016.12.56,因此我们继续执行此操作,知道日期合法。需要注意的是每当月份等于12的时候,再加的时候,则年会变化,如上2016.12.56再加12的月的31天就变成了2017.1.25,此时日期合法,退出循环。代码如下:

Date Date::operator+(int day){Date temp(*this);if (day < 0) { //考虑到date + -50这种情况,直接调用date - 50的函数day = -day;return temp - day;}temp._day += day;while (temp._day > GetDaysInMonth(temp._year, temp._month)) {temp._day -= GetDaysInMonth(temp._year, temp._month);if (temp._month == 12) {temp._year++;temp._month = 1;}else {temp._month++;}}return temp;}

在写完这个之后我们的自增运算就简单了,如下:

Date& Date::operator++()//前置++形如++a{return (*this = *this + 1);}Date Date::operator++(int)//后置++形如a++{Date temp(*this);*this = *this + 1;return temp;}

有了这些,我们在计算两个日期的相差天数就简单多了,比如2016.10.17和2017.3.1,我们不妨设置相差天数为day,将小日期+day=大日期进行一个循环,得到天数,代码如下:

int Date::operator-(const Date& date){Date maxDate(*this);Date minDate(date);if (maxDate < minDate) {maxDate = date;minDate = *this;}int days = 0;while (1) {if (minDate + days == maxDate)break;days++;}return days;}

加法出来了,减法的思路基本同上,就不再赘述了,其他比较简单的代码就不做解释了,以下给出所有的实现代码:

ostream& operator<<(ostream& _cout, const Date& date){_cout << date._year << "/" << date._month << "/" << date._day;return _cout;}istream& operator>>(istream& _cin, Date& date){_cin >> date._year >> date._month >> date._day;return _cin;}Date::Date(int year, int month, int day){if (year > 0 && (month > 0 && month < 13) &&(day > 0 && day <= GetDaysInMonth(year, month))){_year = year;_month = month;_day = day;}else {cout << "the date is illegal\n";}}Date::Date(const Date& date) : _year(date._year), _month(date._month), _day(date._day) {}Date& Date::operator=(const Date& date){if (this != &date) {_year = date._year;_month = date._month;_day = date._day;}return *this;}Date Date::operator+(int day){Date temp(*this);if (day < 0) {day = -day;return temp - day;}temp._day += day;while (temp._day > GetDaysInMonth(temp._year, temp._month)) {temp._day -= GetDaysInMonth(temp._year, temp._month);if (temp._month == 12) {temp._year++;temp._month = 1;}else {temp._month++;}}return temp;}Date& Date::operator++()//前置++形如++a{return (*this = *this + 1);}Date Date::operator++(int)//后置++形如a++{Date temp(*this);*this = *this + 1;return temp;}Date Date::operator-(int day){Date temp(*this);temp._day -= day;while (temp._day <= 0) {if (temp._month == 1) {temp._year--;temp._month = 12;}else {temp._month--;}temp._day += GetDaysInMonth(temp._year, temp._month);}return temp;}int Date::operator-(const Date& date){Date maxDate(*this);Date minDate(date);if (maxDate < minDate) {maxDate = date;minDate = *this;}int days = 0;while (1) {if (minDate + days == maxDate)break;days++;}return days;}Date& Date::operator--(){return (*this = *this - 1);}Date Date::operator--(int){Date temp(*this);*this = *this - 1;return temp;}bool  Date::operator>(const Date& date){if (_year > date._year || (_year == date._year && _month > date._month) || (_year == date._year && _month == date._month && _day > date._day)){return true;}elsereturn false;}bool  Date::operator<(const Date& date){if (_year < date._year || (_year == date._year && _month < date._month) || (_year == date._year && _month == date._month && _day < date._day)){return true;}elsereturn false;}bool  Date::operator==(const Date& date){return _year == date._year && _month == date._month && _day == date._day;}bool  Date::operator!=(const Date& date){return _year != date._year || _month != date._month || _day != date._day;}bool  Date::operator>=(const Date& date){if (*this < date)return false;elsereturn true;}bool  Date::operator<=(const Date& date){if (*this > date)return false;elsereturn true;}void FunTest(){Date date(2016, 11, 17);cout << ++date << endl;cout << --date << endl;cout << date << endl;cout << date-- << endl;cout << date++ << endl;cout << date << endl;date = Date(2016, 10, 17);cout << date + 100 << endl;Date date2(1996, 3, 1);cout << date2 - 100 << endl;cout << boolalpha << (Date(2016, 10, 1) <= date) << endl;cout << (Date(2017, 3, 1) - Date(2016, 10, 17)) << endl;}int main(){FunTest();getchar();return 0;}




2 0