日期类模板 , 该日期是第几天,第几天的日期,两个日期的差 ,一个日期的n天之后的日期...

http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2315

http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10498

以上是验证模板的题目


/*
 * 模板有风险,使用需谨慎 ,
 * 在获取某年的天数时,可以打表
 *
 */
// 声明
struct Time ;
inline bool IsrunYear( int const & year );
// 输入一个日期, 返回是这年的第几天
int Cnt_day_of_year( Time const& time);
// 得到这年的第几天这个日期
Time Time_of_nTH_day(int const&year,int days);
//获取某年的天数
inline int getdayOFyear( int y );
//计算两个日期相差的天数
int  Cnt_day_between_Times(Time t1,Time t2);
// 一个日期n天后的日期
Time next_Days_after_Time( Time time,int days );
// 1.是闰年 0.是平年
extern int dayOFmonth[2][13] ;


#include <cstdio>
#include <iostream>
using namespace std;
struct Time{
    int year,month,day;
    Time(int y = 0,int m = 0,int d = 0) : year(y),month(m),day(d){}
};
inline bool IsrunYear( int const & year ){

    return ( (year % 4 == 0 && year % 100 != 0 ) || ( year % 400 == 0 ) );
}
// 1.是闰年 0.是平年
int dayOFmonth[2][13] = {
    // 1  2  3  4  5  6  7  8  9  10 11 12
{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}
};


// 输入一个日期, 返回是这年的第几天
int Cnt_day_of_year( Time const& time){
    int days(0);
    bool flag = IsrunYear(time.year);
    for (int i = 1;i < time.month;++i )
        days += dayOFmonth[flag][i];
    days += time.day;
    return days ;
}

// 得到这年的第几天这个日期
Time Time_of_nTH_day(int const&year,int days){
    Time time(year,1,1);
    bool flag = IsrunYear( year );
    for ( int i = 1; i <= 12;++i ){
        if( days <= dayOFmonth[flag][i]) break;
        time.month++;
        days -= dayOFmonth[flag][i];
    }
    time.day = days;
    return time;
}

// 这段优化基本没用
int days_Of_year[2222]={0};
inline void sieve(){
    for (int i = 1800 ; i <= 2200;++i )
        days_Of_year[i] = IsrunYear(i) ? 366 : 365;
}

//获取某年的天数
inline int getdayOFyear( int y ){
    return IsrunYear( y ) ? 366 : 365;
}

//计算两个日期相差的天数
int  Cnt_day_between_Times(Time t1,Time t2){
    //2010/3/20-2010/1/10=69
    //printf("%d/%d/%d-%d/%d/%d=",t1.year,t1.month,t1.day,t2.year,t2.month,t2.day);
    int d1 = 0,d2 = 0;
    bool flag1 = IsrunYear( t1.year ) ,
         flag2 = IsrunYear( t2.year ) ;
    if ( t1.year == t2.year )
    {
        if (t1.month == t2.month )
            return t1.day-t2.day;
        else{
            d1 = t1.day + dayOFmonth[flag1][t2.month] - t2.day;
            for (int i = t2.month+1 ; i <= t1.month-1;++i)
                d1 += dayOFmonth[flag1][i];
            return d1;
        }
    }else{
        d1 = t1.day;
        for(int i = 1;i <= t1.month-1;i++)
            d1 += dayOFmonth[flag1][i];
        d2 = dayOFmonth[flag2][t2.month] - t2.day;
        for (int i = 12;i >= t2.month+1;--i)
            d2 += dayOFmonth[flag2][i];
        for (int y = t2.year+1;y <= t1.year-1;++y)
            d2 += getdayOFyear( y );
        return d1+d2;
    }
}

// 一个日期n天后的日期
Time next_Days_after_Time( Time time,int days ){
    Time ans(0,0,0);
    int CntDay =  Cnt_day_of_year( time );
    int leave = getdayOFyear(time.year) - CntDay ;
    if( days <= leave ){
        ans = Time_of_nTH_day( time.year, CntDay + days );
    }else {
        days -= leave , time.year++;
        while( days > days_Of_year[time.year] )
            days -= days_Of_year[time.year] ,  time.year++;
        ans = Time_of_nTH_day(time.year,days);
    }
    return ans;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值