//
LiuKai @ HUST
// 2006-7-28 && 2006-7-30
/**/ /************************************************************************************
Date.cpp 完整的Date类声明与实现,以1970年1月1日为起点
使用延迟求值和分配技术
************************************************************************************/
#include < iostream >
#include < string >
#include < sstream >
#include < conio.h >
using namespace std;
class cache
... {
friend class Date;
cache()
:isValid(false),rep(0)...{}
~cache()
...{
delete rep;
}
bool isValid;
string* rep;
} ;
class Date
... {
public:
enum Month...{ jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };
class Bad_date...{};
//constructors
Date( int dd, Month mm, int yy );
Date( int total );
Date( const Date& original );
//destructor
~Date()
...{
delete cachePtr;
}
//Read only functions
int day() const;
Month month() const;
int year() const;
int getTotal() const;
string string_rep() const;
//Modify functions
Date& add_year(int n=1);
Date& add_month(int n=1);
Date& add_day(int n=1);
//overloaded operators
friend bool operator==( Date a, Date b );
friend bool operator!=( Date a, Date b );
friend bool operator>( Date a, Date b );
friend bool operator<( Date a, Date b );
Date& operator++();
Date& operator--();
Date& operator+=( int n );
Date& operator-=( int n );
Date& operator=( const Date& );
Date operator+( int n );
Date operator-( int n );
int operator-( Date b );
private:
int totalDay; //days after 1970.1.1
int DMYtoInt( int dd, Month mm, int yy );
mutable int d;
mutable int m;
mutable int y;
bool isModified; //如果有改动,则要重新计算d,m,y
void ComputeDMY( void ) const; //设置为const是为了const函数使用
cache *cachePtr;
void MakeStr( void ) const; //lazy evaluation and allocation
} ;
// global function declarations
bool isLeap( int year ); // 判断闰年
int getMonthDay( int year, Date::Month mon ); // 返回某年某个月的天数
// implementations
// constructors
Date::Date( int dd, Month mm, int yy )
:d(dd),m(mm),y(yy),cachePtr( new cache ),isModified( true )
... {
totalDay = DMYtoInt( d, Date::Month(m), y );
}
Date::Date( int total )
:cachePtr( new cache ),isModified( true ),totalDay(total)
... {
//compute d, m, y
ComputeDMY();
}
Date::Date( const Date & original )
:totalDay( original.getTotal() ), cachePtr( new cache ), isModified( true )
... {
//Nothing
}
// Read only functions
int Date::day() const
... {
if( this->isModified )
ComputeDMY();
return d;
}
Date::Month Date::month() const
... {
if( this->isModified )
ComputeDMY();
return Month(m);
}
int Date::year() const
... {
if( this->isModified )
ComputeDMY();
return y;
}
int Date::getTotal() const
... {
return totalDay;
}
string Date::string_rep() const
... {
if( !cachePtr->isValid )
...{
this->MakeStr();
cachePtr->isValid = true;
}
return *(cachePtr->rep);
}
// Modify functions
Date & Date::add_year( int n)
... {
y = this->year() + n;
totalDay = DMYtoInt(d,Month(m),y);
this->isModified = true;
this->cachePtr->isValid = false;
return *this;
}
Date & Date::add_month( int n)
... {
m = this->month() + n;
totalDay = DMYtoInt(d,Month(m),y);
this->isModified = true;
this->cachePtr->isValid = false;
return *this;
}
Date & Date::add_day( int n)
... {
this->totalDay += n;
this->isModified = true;
this->cachePtr->isValid = false;
return *this;
}
// help functions
void Date::ComputeDMY( void ) const
... {
//d,m,y均为mutable,可以改变
//TODO:把totalDay转化为d,m,y
y = 1970;
m = Month(1);
d = 1;
int rest = totalDay;
//以四年为单位
const int daysInFourYear = 4 * 365 + 1;
int fourYearNum = rest / daysInFourYear;
rest %= daysInFourYear;
y += fourYearNum*4;
//判断为四年中的哪一年,1970正好处在两个闰年正中心,故正负一起考虑
const int firstYear = 365;
const int secondYear = 365*2;
const int thirdYear = 365*3+1; //leap year:1972
if( rest/firstYear == 0 ) //1970+-
...{
//first year, do nothing
}
else if( rest/secondYear == 0 ) //1971+ or 1969-
...{
y += rest/firstYear;
rest %= firstYear;
}
else if( rest/thirdYear == 0 ) //1972+ or 1968-
...{
if( rest >=0 )
...{
y += 2;
rest -= secondYear;
}
else
...{
y -= 2;
rest += secondYear+1;
}
}
else //1973+ or 1967-
...{
y += rest>0 ? 3: -3 ;
rest %= thirdYear;
}
//已经确定年份,确定是哪一月,这时就需要将rest的正负情况分开
int monthday;
if( rest>= 0 )
...{
monthday = getMonthDay(y,Month(m));
while( rest - monthday >= 0 )
...{
m++;
rest -= monthday;
monthday = getMonthDay(y,Month(m));
}
d += rest;
}
else //rest<0, 本年的1月1日相当于前一年的12月32日
...{
y--;
m = 12;
d = getMonthDay(y,Month(m))+1;
while( rest + d <= 0 )
...{
m--;
rest += d;
d = getMonthDay(y,Month(m));
}
d += rest;
}
} // end function ComputeDMY
int Date::DMYtoInt( int dd, Month mm, int yy )
... {
int sum = 0;
int fourYearNum = 0; //以四年为单位
int yearNum; //四年中的哪一年
const int daysInFourYear = 4 * 365 + 1;
const int daysInYear = 365;
if( yy >= 1970 )
...{
fourYearNum = (yy-1970) / 4;
sum += fourYearNum * daysInFourYear;
yearNum = (yy-1970) % 4;
sum += yearNum * daysInYear;
if( yearNum > 2 )
sum++; //过了闰年
for( int i = 1; i < mm; i++ )
...{
sum += getMonthDay( yy, Month(i) );
}
sum += (dd-1);
}
else
...{
fourYearNum = (1970-yy) / 4;
sum -= fourYearNum * daysInFourYear;
yearNum = (1970-yy) % 4;
sum -= yearNum * daysInYear;
if( yearNum >= 2 )
sum--;
for( int j = 1; j < mm; j++ )
...{
sum += getMonthDay( yy, Month(j) );
}
sum += ( dd - 1 );
}
return sum;
}
void Date::MakeStr( void ) const // lazy evaluation and allocation
... {
if( !cachePtr->isValid )
...{
if( !cachePtr->rep )
cachePtr->rep = new string("",11);
ostringstream os(*cachePtr->rep);
os << year() << '-' << month() << '-' << day() << '
// 2006-7-28 && 2006-7-30
/**/ /************************************************************************************
Date.cpp 完整的Date类声明与实现,以1970年1月1日为起点
使用延迟求值和分配技术
************************************************************************************/
#include < iostream >
#include < string >
#include < sstream >
#include < conio.h >
using namespace std;
class cache
... {
friend class Date;
cache()
:isValid(false),rep(0)...{}
~cache()
...{
delete rep;
}
bool isValid;
string* rep;
} ;
class Date
... {
public:
enum Month...{ jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };
class Bad_date...{};
//constructors
Date( int dd, Month mm, int yy );
Date( int total );
Date( const Date& original );
//destructor
~Date()
...{
delete cachePtr;
}
//Read only functions
int day() const;
Month month() const;
int year() const;
int getTotal() const;
string string_rep() const;
//Modify functions
Date& add_year(int n=1);
Date& add_month(int n=1);
Date& add_day(int n=1);
//overloaded operators
friend bool operator==( Date a, Date b );
friend bool operator!=( Date a, Date b );
friend bool operator>( Date a, Date b );
friend bool operator<( Date a, Date b );
Date& operator++();
Date& operator--();
Date& operator+=( int n );
Date& operator-=( int n );
Date& operator=( const Date& );
Date operator+( int n );
Date operator-( int n );
int operator-( Date b );
private:
int totalDay; //days after 1970.1.1
int DMYtoInt( int dd, Month mm, int yy );
mutable int d;
mutable int m;
mutable int y;
bool isModified; //如果有改动,则要重新计算d,m,y
void ComputeDMY( void ) const; //设置为const是为了const函数使用
cache *cachePtr;
void MakeStr( void ) const; //lazy evaluation and allocation
} ;
// global function declarations
bool isLeap( int year ); // 判断闰年
int getMonthDay( int year, Date::Month mon ); // 返回某年某个月的天数
// implementations
// constructors
Date::Date( int dd, Month mm, int yy )
:d(dd),m(mm),y(yy),cachePtr( new cache ),isModified( true )
... {
totalDay = DMYtoInt( d, Date::Month(m), y );
}
Date::Date( int total )
:cachePtr( new cache ),isModified( true ),totalDay(total)
... {
//compute d, m, y
ComputeDMY();
}
Date::Date( const Date & original )
:totalDay( original.getTotal() ), cachePtr( new cache ), isModified( true )
... {
//Nothing
}
// Read only functions
int Date::day() const
... {
if( this->isModified )
ComputeDMY();
return d;
}
Date::Month Date::month() const
... {
if( this->isModified )
ComputeDMY();
return Month(m);
}
int Date::year() const
... {
if( this->isModified )
ComputeDMY();
return y;
}
int Date::getTotal() const
... {
return totalDay;
}
string Date::string_rep() const
... {
if( !cachePtr->isValid )
...{
this->MakeStr();
cachePtr->isValid = true;
}
return *(cachePtr->rep);
}
// Modify functions
Date & Date::add_year( int n)
... {
y = this->year() + n;
totalDay = DMYtoInt(d,Month(m),y);
this->isModified = true;
this->cachePtr->isValid = false;
return *this;
}
Date & Date::add_month( int n)
... {
m = this->month() + n;
totalDay = DMYtoInt(d,Month(m),y);
this->isModified = true;
this->cachePtr->isValid = false;
return *this;
}
Date & Date::add_day( int n)
... {
this->totalDay += n;
this->isModified = true;
this->cachePtr->isValid = false;
return *this;
}
// help functions
void Date::ComputeDMY( void ) const
... {
//d,m,y均为mutable,可以改变
//TODO:把totalDay转化为d,m,y
y = 1970;
m = Month(1);
d = 1;
int rest = totalDay;
//以四年为单位
const int daysInFourYear = 4 * 365 + 1;
int fourYearNum = rest / daysInFourYear;
rest %= daysInFourYear;
y += fourYearNum*4;
//判断为四年中的哪一年,1970正好处在两个闰年正中心,故正负一起考虑
const int firstYear = 365;
const int secondYear = 365*2;
const int thirdYear = 365*3+1; //leap year:1972
if( rest/firstYear == 0 ) //1970+-
...{
//first year, do nothing
}
else if( rest/secondYear == 0 ) //1971+ or 1969-
...{
y += rest/firstYear;
rest %= firstYear;
}
else if( rest/thirdYear == 0 ) //1972+ or 1968-
...{
if( rest >=0 )
...{
y += 2;
rest -= secondYear;
}
else
...{
y -= 2;
rest += secondYear+1;
}
}
else //1973+ or 1967-
...{
y += rest>0 ? 3: -3 ;
rest %= thirdYear;
}
//已经确定年份,确定是哪一月,这时就需要将rest的正负情况分开
int monthday;
if( rest>= 0 )
...{
monthday = getMonthDay(y,Month(m));
while( rest - monthday >= 0 )
...{
m++;
rest -= monthday;
monthday = getMonthDay(y,Month(m));
}
d += rest;
}
else //rest<0, 本年的1月1日相当于前一年的12月32日
...{
y--;
m = 12;
d = getMonthDay(y,Month(m))+1;
while( rest + d <= 0 )
...{
m--;
rest += d;
d = getMonthDay(y,Month(m));
}
d += rest;
}
} // end function ComputeDMY
int Date::DMYtoInt( int dd, Month mm, int yy )
... {
int sum = 0;
int fourYearNum = 0; //以四年为单位
int yearNum; //四年中的哪一年
const int daysInFourYear = 4 * 365 + 1;
const int daysInYear = 365;
if( yy >= 1970 )
...{
fourYearNum = (yy-1970) / 4;
sum += fourYearNum * daysInFourYear;
yearNum = (yy-1970) % 4;
sum += yearNum * daysInYear;
if( yearNum > 2 )
sum++; //过了闰年
for( int i = 1; i < mm; i++ )
...{
sum += getMonthDay( yy, Month(i) );
}
sum += (dd-1);
}
else
...{
fourYearNum = (1970-yy) / 4;
sum -= fourYearNum * daysInFourYear;
yearNum = (1970-yy) % 4;
sum -= yearNum * daysInYear;
if( yearNum >= 2 )
sum--;
for( int j = 1; j < mm; j++ )
...{
sum += getMonthDay( yy, Month(j) );
}
sum += ( dd - 1 );
}
return sum;
}
void Date::MakeStr( void ) const // lazy evaluation and allocation
... {
if( !cachePtr->isValid )
...{
if( !cachePtr->rep )
cachePtr->rep = new string("",11);
ostringstream os(*cachePtr->rep);
os << year() << '-' << month() << '-' << day() << '