计算从某个日期开始往前或往后天数的日期

基本需求:给出一个日期,可以是当天日期,计算往前N天或者往后N天的日期。

给出的算法基本思路:

1.设定一个基础日期,比如1901-1-1

2.先算出给定日期和基础日期之间的天数n

3.往前m天或往后m天,则得到的日期天数n1=n+/- m

4.n1天数用基础天数做为起点,算出日期

const int month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int month_days_leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

const int days_number = 365;
const int days_number_leap = 366;
const int base_yy = 1901;

inline bool is_leap_year(const int yy)
{
    if( (yy % 4 == 0 && yy % 100 != 0) || yy % 400 == 0)
        return true;
    else
        return false;
}

// 计算从base_yy-1-1到当前年份的天数
int date2offset(const int yy, const int mm, const int dd)
{
    if(yy < base_yy)
        return -1;
    int number_d = 0;
    int i = 0;
    int diff = yy - base_yy;
    
    
    while (i < diff) {
        if(is_leap_year(base_yy + i))
            number_d += days_number_leap;
        else
            number_d += days_number;
        i ++;
    }
    const int *pd = is_leap_year(yy) ? month_days_leap : month_days;
    i = 1;
    while(i < mm)
    {
        number_d += pd[i - 1];
        i++;
    }
    number_d = number_d + (dd - 1);
    
    return  number_d;
}
//天数转换成具体日期
int offset2date(const int number_d, int &yy, int &mm, int &dd)
{
    if(number_d < 0){
        printf("wrong number_d :%d\n", number_d);
        return -1;
    }
    //实际年份应该在year1之后
    int year1 = number_d / days_number_leap + base_yy;

    int days = date2offset(year1, 1, 1);
    
    while (days <= number_d)
    {
        bool bleap = is_leap_year(year1);
        int days_add = days + (bleap ? days_number_leap : days_number);
        if( days_add < number_d)
        {
            year1 ++;
            days = days_add;
        }else if(days_add == number_d)
        {
            yy = year1 + 1;
            mm = 1;
            dd = 1;
            break;
        }else
        {
            yy = year1;
            const int *pd = bleap ? month_days_leap : month_days;
            int i = 0;
            while(i < 12)
            {
                int add_mm = days + pd[i];
                if(add_mm < number_d)
                {
                    i++;
                    days = add_mm;
                }else if(add_mm == number_d)
                {
                    mm = i + 2;
                    if(mm == 13)
                    {
                        printf("wrong month\n");
                        yy ++;
                        mm = 1;
                        
                    }
                    dd = 1;
                    break;
                    
                }else{
                    mm = i + 1;
                    
                    dd = number_d - days + 1;
                    break;
                }
            }//end while i < 12
            break;
        }//end else
        
    }
    
    return 0;
}


void getdays(const int yy, const int mm, const int dd, const int days)
{
    printf("in:%04d-%02d-%02d, days = %d\n", yy, mm, dd, days);
    int number = date2offset(yy, mm, dd);
    printf("number = %d\n", number);
    int y1 = 0;
    int m1 = 0;
    int d1 = 0;
    offset2date(number + days, y1, m1, d1);
    printf("out:%04d-%02d-%02d\n", y1, m1, d1);
    
}

int main(int argc, const char * argv[])
{
    int yy = 2014;
    int mm = 8;
    int dd = 31;
    int days = -10000;
    getdays(yy, mm, dd, days);
    return 0;
}


当然如果需要计算的年份比1901还小,只要修改下base_yy的值即可。

大家有什么其它更好的算法可以一起分享下。

此文在看了一篇“一个精巧的日期算法”后,自己想了一个算法实现,网上那个精巧算法更加精简。


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值