#include "Date.h"
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <algorithm> // For swap()
#include <ctime>
#include <cassert>
#include <iomanip>
using namespace std;
namespace {
const int daysInMonth[][13] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
},
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}
};
inline bool isleap(int y) {
return y%4 == 0 && y%100 != 0 || y%400 ==
0;
}
}
Date::Date() {
time_t tval = time(0);
struct tm *now = localtime(&tval);
year = now->tm_year + 1900;
month = now->tm_mon + 1;
day = now->tm_mday;
}
Date::Date(int yr,int mon,int dy)
throw(Date::DateError) {
if(!(1 <= mon && mon <= 12))
throw DateError("Bad month in Date
ctor");
if(!(1 <= dy && dy <=
daysInMonth[isleap(year)][mon]))
throw DateError("Bad day in Date ctor");
year = yr;
month = mon;
day = dy;
}
Date::Date(const std::string& s)
throw(Date::DateError) {
if(!(s.size() == 8))
throw DateError("Bad string in Date
ctor");
for(int n = 8; --n >= 0;)
if(!isdigit(s[n]))
throw DateError("Bad string in Date
ctor");
string buf = s.substr(0, 4);
year = atoi(buf.c_str());
buf = s.substr(4, 2);
month = atoi(buf.c_str());
buf = s.substr(6, 2);
day = atoi(buf.c_str());
if(!(1 <= month && month <= 12))
throw DateError("Bad month in Date
ctor");
if(!(1 <= day && day
<=
daysInMonth[isleap(year)][month]))
throw DateError("Bad day in Date ctor");
}
int Date::getYear() const { return year; }
int Date::getMonth() const { return month; }
int Date::getDay() const { return day; }
string Date::toString() const {
ostringstream os;
os.fill('0');
os << setw(4) << year
<< setw(2) << month
<< setw(2) << day;
return os.str();
}
int Date::compare(const Date& d2) const {
int result = year - d2.year;
if(result == 0) {
result = month - d2.month;
if(result == 0)
result = day - d2.day;
}
return result;
}
int Date::daysInPrevMonth(int year, int month) {
if(month == 1) {
--year;
month = 12;
}
else
--month;
return daysInMonth[isleap(year)][month];
}
bool operator<(const Date& d1, const Date&
d2) {
return d1.compare(d2) < 0;
}
bool operator<=(const Date& d1, const Date&
d2) {
return d1 < d2 || d1 == d2;
}
bool operator>(const Date& d1, const Date&
d2) {
return !(d1 < d2) && !(d1 == d2);
}
bool operator>=(const Date& d1, const Date&
d2) {
return !(d1 < d2);
}
bool operator==(const Date& d1, const Date& d2)
{
return d1.compare(d2) == 0;
}
bool operator!=(const Date& d1, const Date& d2)
{
return !(d1 == d2);
}
Date::Duration
duration(const Date& date1, const Date& date2)
{
int y1 = date1.year;
int y2 = date2.year;
int m1 = date1.month;
int m2 = date2.month;
int d1 = date1.day;
int d2 = date2.day;
int order = date1.compare(date2);
if(order == 0)
return Date::Duration(0,0,0);
else if(order > 0) {
using std::swap;
swap(y1, y2);
swap(m1, m2);
swap(d1, d2);
}
int years = y2 - y1;
int months = m2 - m1;
int days = d2 - d1;
assert(years > 0 ||
years == 0 && months > 0 ||
years == 0 && months == 0 && days
> 0);
int lastMonth = m2;
int lastYear = y2;
while(days < 0) {
assert(months > 0);
days += Date::daysInPrevMonth(
lastYear, lastMonth--);
--months;
}
if(months < 0) {
assert(years > 0);
months += 12;
--years;
}
return Date::Duration(years, months, days);
}
ostream& operator<<(ostream& os, const
Date& d) {
char fillc = os.fill('0');
os << setw(2) << d.getMonth() <<
‘-‘
<< setw(2) << d.getDay() << ‘-‘
<< setw(4) << setfill(fillc) <<
d.getYear();
return os;
}
istream& operator>>(istream& is,
Date& d) {
is >> d.month;
char dash;
is >> dash;
if(dash != '-')
is.setstate(ios::failbit);
is >> d.day;
is >> dash;
if(dash != '-')
is.setstate(ios::failbit);
is >> d.year;
return is;
}