// date class function definitions // preprocessor directives #include #include #include using namespace std; #include "date.h" #include "myio.h" //********************************************************************** // default constructor to initialize to todays date // // post-condition -- the date will be todays date //********************************************************************** Date::Date() { *this = today(); } //********************************************************************** // constructor to initialize to yr/mon/day // // parameter usage : yr -- imports the year to use for the date // mon -- imports the month to use for the date // day -- imports the day to use for the date // // post-condition -- if the parameters are valid the date will be yr/mon/day // otherwise it will be todays date //********************************************************************** Date::Date(int yr, int mon, int day) { if (validDate(yr, mon, day)) { yy = yr; // set date to the entered date mm = mon; dd = day; } else { // date was not valid so use today *this = today(); } } //********************************************************************* // assign an integer date to this object // // parameter usage : date -- imports an integer representing a date // // post-condition -- if the parameter represents a valid date; the // assignment is done; otherwise no change is made //********************************************************************* Date& Date::operator=(int date) { int day = date % 100; // extract the day date /= 100; // date now is yyyymm int mon = date%100; // extract the month int yr = date/100; // extract the year setDate(yr,mon,day); // this will ensure the date is valid return *this; } //********************************************************************** // function to return this objects year //********************************************************************** int Date::year() const { return yy; } //********************************************************************** // function to return this objects month //********************************************************************** int Date::month() const { return mm; } //********************************************************************** // function to return this objects day //********************************************************************** int Date::day() const { return dd; } //********************************************************************** // function to add a specified number of years to this objects date. // // parameter usage : // numYrs -- imports the number of years to add to this objects date. // // post-condition -- the date is adjusted by numYr; if numYrs > 0 // they are added to the date, if < 0 they are subtracted // from the date. If the result would be an invalid year // then the date is not changed. //********************************************************************** void Date::addYear(int numYrs) { if (yy+numYrs >= baseYear) { // only adjust the year if it will be valid yy += numYrs; // in a non leap year we can not have Feb 29 so change it to the 28th if (!leapYear(yy) && mm == 2 && dd == 29) dd = 28; } } //********************************************************************** // function to add a specified number of months to this objects date. // // parameter usage : numMonths -- imports the number of months to add // // post-condition -- the date is adjusted by numMonths; if numMonths > 0 // they are added to the date, if < 0 they are subtracted // from the date. //********************************************************************** void Date::addMonth(int numMonths) { mm += numMonths; while (mm > 12) { // while more months than in a year mm -= 12; // reduce number of months and yy++; // adjust to next year } while (mm < 1) { // while less months than in a year mm += 12; // increase number of months and yy--; // adjust to prev year } // adjust end of month if dd is past end of current month // this will ensure that the date is always valid, i.e we do not end // up with Feb 30 or something if (dd > daysIn(mm,yy)) dd = daysIn(mm,yy); } //********************************************************************** // function to add a specified number of weeks to this objects date. // // parameter usage : numWeeks -- imports the number of weeks to add // // post-condition -- the date is adjusted by numWeeks; if numWeeks > 0 // they are added to the date, if < 0 they are subtracted // from the date. //********************************************************************** void Date::addWeek(int numWeeks) { addDay(7*numWeeks); } //********************************************************************** // function to add a specified number of days to this objects date. // // parameter usage : numDays -- imports the number of days to add // // post-condition -- the date is adjusted by numDays; if numDays > 0 // they are added to the date, if < 0 they are subtracted // from the date. //********************************************************************** void Date::addDay(int numDays) { dd += numDays; while (dd > daysIn(mm,yy)) { // while more days than in current month dd -= daysIn(mm,yy); // subtract number of days in current month mm++; // go to next month if (mm > 12) { // check for new year and adjust if necessary mm = 1; yy++; } } while (dd < 1) { // while fewer days than in a month mm--; // go to prev month if (mm < 1) { // check for new year and adjust if necessary mm = 12; yy--; } dd += daysIn(mm,yy); // add number of days in this month } } //*********************************************** // function to pre-increment this objects day //*********************************************** Date Date::operator++() { addDay(1); return *this; // return the incremented date } //*********************************************** // function to post-increment this objects day //*********************************************** Date Date::operator++(int) { Date temp = *this; // save the current date to return addDay(1); return temp; // return the date as it was before } //*********************************************** // function to pre-decrement this objects day //*********************************************** Date Date::operator--() { addDay(-1); return *this; // return the decremented date } //*********************************************** // function to post-decrement this objects day //*********************************************** Date Date::operator--(int) { Date temp = *this; // save the current date to return addDay(-1); return temp; // return the date as it was before // incrementing } //********************************************************************** // function to return true if the date is the same as the date argument // // parameter usage : date -- imports the date to be compared with // // post-condition -- returns true if it is the same date //********************************************************************** bool Date::operator==(const Date &date) const { return (dd == date.dd && mm == date.mm && yy == date.yy); } //********************************************************************** // function to return true if the date comes before the date argument. // // parameter usage : date -- imports the date to be compared with // // post-condition -- returns true if it comes before //********************************************************************** bool Date::operator<(const Date &date) const { return (yy < date.yy || (yy == date.yy && mm < date.mm) || (yy == date.yy && mm == date.mm && dd < date.dd) ); } //*********************************************** // function to return true if yy is a * // leap year. * // year -- imports the year to be tested * //*********************************************** bool Date::leapYear(int year) { return (year % 400==0 || year % 4 == 0 && year % 100 != 0 ); } //*********************************************** // function to return todays date * //*********************************************** Date Date::today() { time_t unixTime = time(NULL); // set unixTime to the unix representation // of the current time tm* currDate = localtime(&unixTime);// convert the unix representation to // a structure so that we can access // required fields for the time. // localtime returns a pointer to // a structure which has these fields return Date(1900+currDate->tm_year, // create a Date object using the currDate->tm_mon+1, // fields of the built in currDate->tm_mday // time structure ); } //********************************************************************** // print the date in form yyyy/mm/dd // // parameter usage : oStr -- imports the stream to insert into and // exports the modified stream //********************************************************************** void Date::print(ostream& oStr) const { char orig = oStr.fill('0'); oStr << yy << '/' << setw(2) << mm << '/' << setw(2) << dd; oStr << setfill(orig); // reset fill to original character } //********************************************************************** // print the date in form mon dd, yyyy to standard out stream //********************************************************************** void Date::print() const { // an array of strings which are the names for each month; // used to simplify the printing of the month name string monthName[] = {"Jan","Feb","Mar","Apr","May","June", "July","Aug","Sept","Oct","Nov","Dec"}; cout << monthName[mm-1] << ' ' << dd << ", " << yy; } //********************************************************************** // function to prompt user for and read a date //********************************************************************** void Date::read() { cout << "Enter the year -- "; while (true) { getValid(yy); if (yy >= baseYear) break; cout << "Year must be >= " << baseYear << "!! Try again -- "; clrStream(); // clear any garbage after error } clrStream(); // clear any garbage after valid input cout << "Enter the month number -- "; while (true) { getValid(mm); if (1 <= mm && mm <= 12) break; cout << "Month must be between 1 and 12!! Try again -- "; clrStream(); // clear any garbage after error } clrStream(); // clear any garbage after valid input cout << "Enter the day -- "; while (true) { getValid(dd); if (1 <= dd && dd <= daysIn(mm,yy)) break; cout << "Month must be between 1 and " << daysIn(mm,yy) << "!! Try again -- "; clrStream(); // clear any garbage after error } clrStream(); // clear any garbage after valid input } //********************************************************************** // function to read a date. // // parameter usage : iStr -- imports the stream to extract from and // exports the modified stream //********************************************************************** void Date::read(istream &iStr) { int day,mon,yr; char sep1,sep2; iStr >> yr; if (!iStr.good()) return; // invalid data sep1 = iStr.peek(); if (sep1 != '/' && sep1 != ':' && sep1 != '-') { // incomplete date iStr.clear(ios::badbit); return; } // there is a separator coming iStr >> sep1 >> mon; if (!iStr.good()) return; // invalid data sep2 = iStr.peek(); if (sep2 != '/' && sep2 != ':' && sep2 != '-') { // incomplete date iStr.clear(ios::badbit); return; } // there is a separator coming iStr >> sep2 >> day; if (!iStr.good()) return; // invalid data // valid extraction accomplished if (sep2 == sep1) if (setDate(yr,mon,day)) return; // successfully set; outta here else iStr.clear(ios::badbit); // invalid date; set failbit else iStr.clear(ios::badbit); // mismatched separators; set failbit } //********************************************************************** // non-member extraction overload //********************************************************************** istream& operator>>(istream& iStr, Date& date) { date.read(iStr); return iStr; } //********************************************************************** // non-member insertion overload //********************************************************************** ostream& operator<<(ostream& oStr, const Date& date) { date.print(oStr); return oStr; } // utility helper functions //********************************************************************** // set the date to the parameter values // // parameter usage : yr -- imports the year to use for the date // mon -- imports the month to use for the date // day -- imports the day to use for the date // // post-condition -- if the date is valid the date will be set to it // and true will be returned. If invalid, no change is // made and false is returned //********************************************************************** bool Date::setDate(int yr, int mon, int day) { if (validDate(yr,mon,day)) { // if valid change it otherwise do not yy = yr; mm = mon; dd = day; return true; } return false; } //********************************************************************** // function to determine if a date is valid // // parameter usage : yr -- imports the year to check // mon -- imports the month to check // day -- imports the day to check // // post-condition -- returns true if the date is valid //********************************************************************** bool Date::validDate(int year, int mon, int day) { return (year >= baseYear && (mon >= 1 && mon <= 12) && (day > 0 && day <= daysIn(mon,year)) ); } //********************************************************************** // function to determine the number of days in a given month // // parameter usage : yr -- imports the year to use // mon -- imports the month to use // // post-condition -- returns the number of days in the mon for the given yr //********************************************************************** int Date::daysIn(int mon, int yr) { switch(mon) { case 4 : case 6 : case 9 : case 11 : return 30; case 2 : if (leapYear(yr)) return 29; else return 28; default : return 31; } }