Skip to content

C++ Date Class – Manipulate Dates in C++

Finally! I did it! Assignment #4 is complete, and I can manipulate dates pretty effing easily now.

No doubt there is already some vastly superior date manipulation library already out there… stupid school.

:) Just kidding. I learned a LOT with this assignment.


#include <iostream>
using namespace std;

class Date {

private:
	 /*
	|
	 \	PRIVATE DATA
	  |
	*/
	static const int EpochYear = 1752;
	static const int EpochMonth = 9;
	static const int EpochDay = 14;
	static const int EpochDoW = 5;		// must define day of week of epoch (5 = Thursday)
	int epochdays;						// this is the number of days since September 14, 1752
	int month,day,year;					// the current value of month/day/year
	bool validdate;

	 /*
	|
	 \	PRIVATE MEMBER FUNCTIONS
	  |
	*/
	bool isLeapYear(int year){
		// check if this year is a leap year, return false if not
		bool leapyear;

		if ((year % 4) == 0){
			if (year % 100 == 0){
				leapyear = false;
				if (year % 400 == 0){
					leapyear = true;
				}
			} else {
				leapyear = true;
			}
		} else {
			leapyear = false;
		}
		return leapyear;
	}

	int daysInMonth(int m, int y){
		// returns the number of days in a given month (1 =  January, etc)
		// invalid month/year combinations return -1
		int days = -1;
		int febdays = 28;

		if (isLeapYear(y))
			febdays = 29;

		switch (m){
			case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break;
			case 2: days = febdays; break;
			case 4: case 6: case 9: case 11: days = 30; break;
			default: days = -1; break;
		}
		return days;
	}

	int dayOfYear(int m, int d, int y){
		// return the day of year (eg, Jan 1 = 1, Dec 1 = 365 (or 366 on leap years))
		int daycount = 0;		// holds number of days elapsed this year

		// leap through every fully elapsed month
		for (int i=1; i<m; i++){
			daycount += daysInMonth(i,y);
		}

		// don't forget to add the elapsed days of this month
		daycount += d;

		return daycount;
	}

	int getEpochDays(int m, int d, int y){
		// for a given m/d/y, return the number of days since the epoch, 9/14/1752
		int daycount;	// this will be count of epochdays
		int thisDOY = dayOfYear(m,d,y);
		int epochDOY = dayOfYear(EpochMonth,EpochDay,EpochYear);

		// subtract day of year from epoch
		daycount = thisDOY - epochDOY;

		// add days for each fully elapsed year
		while (y > EpochYear){
			y--;	// decrement year now to avoid overcounting leap year
			if (isLeapYear(y)){
				daycount += 366;
			} else {
				daycount += 365;
			}
		}

		return daycount;
	}

	void convertEpochDays(int daysSinceEpoch, int& m, int& d, int& y){
		// SHOULD NOT be using m/d/y variables to calculate!
		int mm = EpochMonth;
		int dd = EpochDay;
		int yyyy = EpochYear;

		while (daysSinceEpoch > 0){
			//cout << "days left: "<< daysSinceEpoch << endl;
			if (daysSinceEpoch >= 366){
				// we have at least a year left
				yyyy++;	// increment year now to avoid taking credit for already elapsed leap day
				if (isLeapYear(yyyy)){
					daysSinceEpoch -= 366;
				} else {
					daysSinceEpoch -= 365;
				}
			} else if (daysSinceEpoch >= 31){
				// we have 31 or more days left
				if (mm == 12){
					daysSinceEpoch -= daysInMonth(mm,yyyy);
					mm = 1;
					yyyy++;
				} else {
					daysSinceEpoch -= daysInMonth(mm,yyyy);
					mm++;
				}
			} else {
				// we have up to 30 days left
				if (dd < daysInMonth(mm,yyyy)){
					dd++;
					daysSinceEpoch--;
				} else if (dd == daysInMonth(mm,yyyy)){
					mm++;
					dd = 1;
					daysSinceEpoch--;
				} else {
					cout << "You didn't account for something!"<< endl;
				}
			}
		}

		m = mm;
		d = dd;
		y = yyyy;
	}

public:
	// constructors
	Date(){
		// set default date to September 14, 1752
		month = 9;
		day = 14;
		year = 1752;
		epochdays = 0;
		validdate = true;
	}

	Date(int m, int d, int y){
		 /*
		|	Sets date with user input, verifies if proper date is provided
		 \	for any problem with user input: status member function will return false
		  | - do not allow date prior to September 14, 1752
		*/	

		// set defaults, assume the user is wrong about everything
		month = 9;
		day = 14;
		year = 1752;
		epochdays = 0;
		validdate = false;

		// month cannot be less than 1 or greater than 12
		if (m >= 1 && m <= 12){
			// month is valid. so far, so good
			// what about days? they can less than <1 or greater than that month's days
			if (d >= 1 && d <= daysInMonth(m,y)){
				// date format is valid, but is it at least 9/14/1752?
				if (getEpochDays(m,d,y) >= 0){
					month = m;
					day = d;
					year = y;
					epochdays = getEpochDays(m,d,y);
					validdate = true;
				}
			}
		}
	}

	// member functions
	bool status(void){
		// if date setting has any problems, returns false
		return validdate;
	}

	bool setdate(int m, int d, int y){
		 /*
		|	Sets date with user input, verifies if proper date is provided
		 \	for any problem with user input, returns false, no date change made
		  | - do not allow date prior to September 14, 1752
		*/	

		bool validnewdate = false;	// assume invalid new date (guilty until proven innocent)

		// month cannot be less than 1 or greater than 12
		if (m >= 1 && m <= 12){
			// month is valid. so far, so good
			// what about days? they can less than <1 or greater than that month's days
			if (d >= 1 && d <= daysInMonth(m,y)){
				// date format is valid, but is it at least 9/14/1752?
				if (getEpochDays(m,d,y) >= 0){
					month = m;
					day = d;
					year = y;
					epochdays = getEpochDays(m,d,y);
					validdate = true;
					validnewdate = true;
				}
			}
		}
		return validnewdate;
	}

	int getmonth(void) const {
		// returns month if status is true (Jan=1, Feb=2, etc)
		// if status is false, returns -1
		if (validdate)
			return month;
		else
			return -1;
	}

	int getday(void) const {
		// returns day if status is true; if status is false returns -1
		if (validdate)
			return day;
		else
			return -1;
	}

	int getyear(void) const {
		// returns year if status is true (eg: 2009,2010,1976)
		// if status is false returns -1
		if (validdate)
			return year;
		else
			return -1;
	}

	bool advance(int i){
		// adds i days to date, i may be positive or negative
		// returns false if there any problems
		if ((epochdays + i) >= 0){
			// increment epochdays to advance date
			epochdays += i;

			// now that we know the new count of epochdays, set m/d/y
			convertEpochDays(epochdays,month,day,year);

			return true;
		} else {
			cerr << "Could not set date prior to September 14, 1752." << endl;
			return false;
		}
	}

	int dleft(void){
		// returns days left in the year (eg, December 1st would return 30)
		int daysleft;

		if (validdate)
			daysleft = dayOfYear(12,31,year) - dayOfYear(month,day,year);
		else
			daysleft = -1;

		return daysleft;
	}

	int diff(Date d){
		 /*
		|	determine the number of day difference from argument
		 \	positive return value means date in argument is after class date, negative means before
		  | (eg; if object date is 2/3/09 and argument d is 2/6/09, function will return 3
		*/
		int m,dom,y,diffDays;
		m = d.getmonth();
		dom = d.getday();
		y = d.getyear();

		if (d.status())
			diffDays = epochdays - getEpochDays(m,dom,y);
		else
			diffDays = 0;	// return 0 for comparisons to invalid dates

		return diffDays;
	}

	int dofw(void){
		 /*
		|	returns day of week (Sunday=1,Monday=2, etc)
		 \	NOTE: September 14th, 1752 was a Thursday (dofw = 5)
		  | So if (epochdays % 7) == 0 then dofw = 5; 1 then dofw = 6; etc
		*/
		int dayofweek;
		if (validdate)
			dayofweek = ((epochdays % 7) + EpochDoW);
		else
			dayofweek = -1;

		return dayofweek;
	}

};

Post a Comment

You must be logged in to post a comment.