C++程序设计语言 特别版 第10章 Date类 完整实现

  这是我实现的C++程序设计语言(特别版)第10章的Date类(放在了书中提到的Chrono名字空间中),是一个比较完整和可靠的版本。实现了所有的成员函数,例如add_day,add_month,以及减少天数的情况,比市面上大多数商业的Date类还要可靠。另外还通过ostringstream实现了string_rep函数,以及leapyear非成员函数。当然,日期加减成员函数的实现风格与原书不太一样,没有用delta_month这种变量计算。。不过很有参考价值。

#ifndef CHRONO_H
#define CHRONO_H

#include <string>
#include <sstream>
namespace Chrono{
 class Date{
 public:
     enum Month{jan=1,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec};
     class Bad_date{};
     Date(int dd=0,Month mm=Month(0),int yy=0);
      
     int day() const{return d;}
     Month month() const{return m;}
     int year() const{return y;}
    
     std::string string_rep() const;
     void char_rep(const char*) const;
    
     Date& add_day(int);
     Date& add_month(int);
     Date& add_year(int);
    
     static void set_default(int,Month,int);
 private:
     int d;
  Month m;
  int y; 
  static Date default_date;
 };
    bool leapyear(int y)
    {
        if(y%100!=0&&y%4==0||y%400==0)
            return true;
        else
            return false;
    }
    int diff(const Date &a,const Date& b);
    Date next_weekday(const Date&);
    Date next_saturday(const Date&);
   
 Date Date::default_date(22,jan,1901);
 void Date::set_default(int dd,Month mm,int yy)
 {
  default_date.d=dd;
  default_date.m=mm;
  default_date.y=yy;
 }
 Date::Date(int dd,Month mm,int yy)
    {
     //数据合法性检验
     if(yy==0) yy=default_date.year();
     if(mm==Month(0)) mm=default_date.month();
     if(dd==0) dd=default_date.day();
     
     int max;     
     switch(mm){
     case feb:
            max=28+leapyear(yy);
   break;
  case apr:case jun:case sep:case nov:
      max=30;
   break;
  case jan:case mar:case may:case jul:case aug:case oct:case dec:
      max=31;
   break;
  default:
      throw Bad_date();
     }
     if(dd<1||max<dd) throw Bad_date();
  
  d=dd;
  m=mm;
  y=yy;
    }
    Date& Date::add_day(int n)
    {
     if(n==0) return *this;
     if(n>0){
         while(true){
             if(n>=365+leapyear(y))
                 n-=365+leapyear(y);
             else
                 break;
          add_year(1);
         }        
         int max;
         while(true){
          switch(m){
          case feb:
              max=28+leapyear(y);
              break;
              case apr:case jun:case sep:case nov:
                  max=30;
                  break;
              case jan:case mar:case may:case jul:case aug:case oct:case dec:
                  max=31;
                  break;
          }
          if(n>=max)
              n-=max;
                else
                    break;
                add_month(1);
         }
         if(d+n>max){
          add_month(1);
          d=d+n-max;
         }
         else
             d=d+n;
            return *this;
     }
     n=-n;
     while(true){
      if(n>=365+leapyear(y))
          n-=365+leapyear(y);
          else
              break;
            add_year(-1);
     }
     int max;
     while(true){
         switch(m){
         case feb:
             max=28+leapyear(y);
             break;
          case apr:case jun:case sep:case nov:
              max=30;
              break;
          case jan:case mar:case may:case jul:case aug:case oct:case dec:
              max=31;
              break;
         }
         if(n>=max)
                n-=max;
            else
                break;
            add_month(-1);
     }
     if(d-n<=0){
      add_month(-1);
         switch(m){
         case feb:
             max=28+leapyear(y);
             break;
          case apr:case jun:case sep:case nov:
              max=30;
              break;
          case jan:case mar:case may:case jul:case aug:case oct:case dec:
              max=31;
              break;
         }
         d=d-n+max;
     }
     else
         d=d-n;
     return *this;
    }
    Date& Date::add_month(int n)
 {
  if(n==0) return *this;  
        if(n>0){
         int delta_year=n/12;
   int mm=m+n%12;
   if(12<mm){
    ++delta_year;
    mm-=12;
   }
   int max;
   switch(m){
   case feb:
       max=28+leapyear(y+delta_year);
                break;
            case apr:case jun:case sep:case nov:
                max=30;
                break;
            case jan:case mar:case may:case jul:case aug:case oct:case dec:
                max=31;
                break;
   }
   if(d>max){
    d=1;
    ++mm;
   }
   m=Month(mm);
   y+=delta_year;  
   return *this;
        }       
        n=-n;
        int delta_year=n/12;
        int mm=m-n%12;
        if(mm<=0){
         ++delta_year;
         mm+=12;
        }
  int max;
  switch(m){
  case feb:
            max=28+leapyear(y+delta_year);
            break;
        case apr:case jun:case sep:case nov:
            max=30;
            break;
        case jan:case mar:case may:case jul:case aug:case oct:case dec:
            max=31;
            break;
  }
  if(d>max){
   d=d-max;
   ++mm;
  }
        m=Month(mm);
        y-=delta_year;
        return *this;
 }
 Date& Date::add_year(int n)
 {
  if(d==29&&m==feb&&leapyear(y+n)){
   m=mar;
   d=1;
  }
  y+=n;
  return *this;
 }
 std::string Date::string_rep() const
 {
  std::ostringstream format_oss;
  format_oss<<d<<" , "<<m<<" , "<<y<<"\n";
  return format_oss.str();
 }
 void Date::char_rep(const char* cstr) const
 {
  std::ostringstream format_oss;
  format_oss<<d<<" , "<<m<<" , "<<y<<"\n";
  cstr=format_oss.str().c_str();
 }
 inline bool operator==(const Date& lhs,const Date& rhs)
 {
  return lhs.day()==rhs.day()&&
         lhs.month()==rhs.month()&&
         lhs.year()==rhs.year();
 } 
}
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值