#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
enum class Month{
jan=1,feb,mar,apr,may,jun,july, aug, sep, oct, nov, dec
};
bool leapyear(int y){
if(y%4) return false;
if (y%100==0 && y%400 ) return false;
return true;
}
int days_in_month(int y, Month m){
static int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(int(m)==2 && leapyear(y)) return 29; //handle feb separately.
else return days[int(m)];
}
class Date{
private:
int y;
Month m;
int d;
public:
Date(int yy,Month mm,int dd):y{yy},m{mm},d{dd}{
//verification code
}
void add_month(int n);
int year() const{return y;}
Month month() const {return m;}
int day() const{return d;}
};
void Date::add_month(int n){ //Assume n>=0
//if(n<0) throw exception("negative month");
int yy=(n/12);// extra years
int mm=n%12;// extra month
int dd=0;
if(mm+int(m)>12) {
++yy;
mm=mm-12;// mm+int(m)<=12
}
// mm+int(m) <= 12
if(d>days_in_month(y+yy,Month(int(m)+mm))){
dd-=days_in_month(y+yy,Month(int(m)+mm));//=>d<days_in_month(int(m)+mm+1) since d-days<=3
++mm; //carry over.
/*
if(int(m)+mm>12){// mm+int(m)=12 and ++mm =>But dec has 31. It can't be happen.
++yy;
mm=mm-12;
}
*/
}
d=d+dd;
m=Month(int(m)+mm);
y+=yy;
}
ostream & operator<<(ostream & os, const Month m){
static string month_tbl[13]={"","jan","feb","mar","apr","may","jun","july", "aug", "sep", "oct", "nov", "dec"};
os<<month_tbl[int(m)];
return os;
}
ostream & operator<<(ostream & os, const Date & d){
os<<d.month()<<"-"<<d.day()<<", "<<d.year();
return os;
}
int main(){
Date d1 {2016, Month::dec,31}, d2 {2016, Month::aug,31},d3{2016,Month::feb,29};
d1.add_month(12);
cout<<d1<<endl;
d2.add_month(4);
cout<<d2<<endl;
d3.add_month(12);
cout<<d3<<endl;
return 0;
}