1. 程式人生 > >C++日期類Date的實現

C++日期類Date的實現

在學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;
	}
	else
		return 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;
	}
	else
		return 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;
	else
		return true;
}

bool  Date::operator<=(const Date& date)
{
	if (*this > date)
		return false;
	else
		return 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;
}