#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
class Date {
public:
// constructors;
Date();
Date(int, int, int);
Date(int, const char *, int);
~Date();
// member functions
int year(void);
int month(void);
int day(void);
Date &operator++(void);
Date &operator--(void);
Date &add_day(int n);
Date &add_month(int m);
Date &add_year(int y);
ostream &operator<<(ostream &);
static char *month_names[];
private:
int Year, Month, Day;
static int months_in_year;
static int days_in_months[];
bool is_skottyear(void);
int maxdays_thismonth(void);
};
int Date::months_in_year = 12;
int Date::days_in_months[13] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char * Date::month_names[12] =
{ "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec" };
// 3 different constructors
Date::Date()
{
Year=0;
Month = Day = 1;
}
Date::Date(int y, int m, int d)
{
Year = y;
Month = m;
Day = d;
}
Date::Date(int y, const char *m, int d)
{
Year = y;
Day = d;
Month = 1;
for (int i=0;i<13;i++)
{
if (strncmp(m, month_names[i], 3) == 0)
{
Month = i;
break;
}
}
}
Date::~Date()
{
cout << "Date object destroyed\n";
}
int Date::year(void)
{
return Year;
}
int Date::month(void)
{
return Month;
}
int Date::day(void)
{
return Day;
}
Date Fakedate;
ostream &operator<<(ostream &stream, Date &date)
{
stream << date.year();
stream.form("-%02d", date.month());
stream.form("-%02d", date.day());
return stream;
}
Date &Date::operator++(void)
{
add_day(1);
return *this;
}
Date &Date::operator--(void)
{
add_day(-1);
return *this;
}
Date &Date::add_year(int y)
{
for (int i=0;i<abs(y);i++)
{
if (is_skottyear())
add_day((int) 366 * abs(y)/y);
else
add_day((int) 365 * abs(y)/y);
}
return *this;
}
Date &Date::add_month(int m)
{
div_t quotrem;
quotrem = div(m, months_in_year);
add_year(quotrem.quot);
for (int i=0;i<abs(quotrem.rem);i++)
add_day((int) maxdays_thismonth() * quotrem.rem/abs(quotrem.rem));
return *this;
}
Date &Date::add_day(int d)
{
while ((Day + d) < 1)
{
if ((Month -= 1) < 1)
{
Month = months_in_year;
Year -= 1;
}
d += maxdays_thismonth();
}
while((Day + d) > maxdays_thismonth())
{
d -= maxdays_thismonth() - Day + 1;
Day = 1;
Month += 1;
if (Month > months_in_year)
{
Month -= months_in_year;
Year += 1;
}
}
Day += d;
return *this;
}
int Date::maxdays_thismonth(void)
{
if (Month == 2 && is_skottyear())
return 29;
else
return days_in_months[Month];
}
bool Date::is_skottyear(void)
{
// i know february had 29 days 1984.
int refyear;
refyear = 1984;
if (((refyear - Year) % 4) == 0)
return true;
else
return false;
}
// prototype this
void get_initdate(int& Y, int& M, int& D);
int main(int argc, char *argv[])
{
Date *dateptr;
Date &somedate = *dateptr;
char choice;
int y, m, d;
get_initdate(y, m, d);
dateptr = new Date(y,m,d);
somedate = *dateptr; // why do i have to do this again? seems unnessecary.
while (1)
{
cout << "<q to quit> or:\n";
cout << "d x = add x days, m x = add x months, y x = add x years,\n";
cout << "a x y z adds x years, y months, z days\n$ ";
cin >> choice;
switch (choice)
{
case 'd':
cin >> d;
somedate.add_day(d);
break;
case 'm':
cin >> m;
somedate.add_month(m);
break;
case 'y':
cin >> y;
somedate.add_year(y);
break;
case 'a':
cin >> y >> m >> d;
somedate.add_year(y).add_month(m).add_day(d);
break;
case '+':
++somedate;
break;
case '-':
--somedate;
break;
case 'q':
exit(false);
break;
default:
cout << "Invalid command\n";
break;
}
cout << "Date: " << somedate << endl;
}
exit (false);
}
void get_initdate(int &Y, int &M, int &D)
{
char *nptr, **endptr;
char readvalue[256];
int val, y, m, d;
FILE *p;
memset(readvalue, 0, 256);
cout << endl << "Enter initial date on form \'year month day\'" << endl;
cout << "Example: \'1974 2 20\' or \'1974 feb 20\' or simply \'today\'" << endl;
cout << "If input is invalid, todays date will be used" << endl;
cout << "$ ";
cin >> readvalue;
// Don't try the below at home folks ;)
nptr = &readvalue[0];
endptr = (char **) malloc(4); // make room for a 32 bit address
*endptr = (char *) malloc(4);
val = strtol(nptr, endptr, 10);
if (**endptr != '\0')
{ // input was not entirely numeric! use todays date
p = popen("date +\"\%Y \%m \%d\"", "r");
fscanf(p, "%d %d %d", &y, &m, &d);
pclose(p);
}
else
{
y = val;
cin >> readvalue;
nptr = &readvalue[0];
val = strtol(nptr, endptr, 10);
if (**endptr != '\0')
{ // input was not entirely numeric! is it a name?
for (int z=0;z<12;z++)
{
if (strncmp(readvalue, Fakedate.month_names[z],3) == 0)
{
m=z+1;
break;
}
}
}
else
m=val;
// and the day...
cin >> readvalue;
nptr = &readvalue[0];
val = strtol(nptr, endptr, 10);
if (**endptr != '\0')
{ // input was not entirely numeric! use todays date
p = popen("date +\"\%Y \%m \%d\"", "r");
fscanf(p, "%d %d %d", &y, &m, &d);
pclose(p);
}
else
d=val;
}
Y=y;
M=m;
D=d;
return;
}