一个日期类的实现和测试(1900-2100年有效)

// 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
{
    
ifthis->isModified )
        ComputeDMY();
    
return d;
}


Date::Month Date::month() 
const
{
    
ifthis->isModified )
        ComputeDMY();
    
return Month(m);
}


int  Date::year()  const
{
    
ifthis->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
++;            //过了闰年

        
forint 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
--;

        
forint 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() << '
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值