计算两个日期相差多少天

/**
 * 思路是循环累加两个相差的年份, 然后再减去较小年份的日期走过多少天, 加上较大年份的日期走过多少天
 * 
 * 比如 2000/04/05-2002/05/02
 * 
 * |----------+---/--------------------------------------|----------+---/
 * 2000       4  5                                      2002       5  2
 * 
 * [----------------for 循环年得到的天数------------------]
 * [-减去走过的天数-]                                     [-加上走过的天数-]
 *                 [----------------------最终天数-----------------------] 
 *           
 */

#include <stdio.h>

static inline int is_leap_year(unsigned int year)
{
    return (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0));
}

typedef struct
{
    int year;
    int month;
    int day;
} rtc_date_t;

const static int month_days[2][13] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31}, /* 润年月 */
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31}, /* 平年月 */
};

/* 计算两个日期相差多少天 */
int dday(rtc_date_t date1, rtc_date_t date2)
{
    rtc_date_t *dmax = date1.year > date2.year ? &date1 : &date2;
    rtc_date_t *dmin = date1.year > date2.year ? &date2 : &date1;

    int days = 0;

    for (int y = dmin->year; y < dmax->year; y++)
        days += is_leap_year(y) ? 366 : 365;

    /* 减去较小的日期走过多少天 */
    int leap = is_leap_year(dmin->year);
    for (int m = 1; m < dmin->month; m++)
        days -= month_days[leap][m - 1];

    /* 加上较大的日期走过多少天 */
    leap = is_leap_year(dmax->year);
    for (int m = 1; m < dmax->month; m++)
        days += month_days[leap][m - 1];

    days += dmax->day - dmin->day;

    return days < 0 ? -days : days;
}

/* 测试 */
int main(int argc, char const *argv[])
{
    rtc_date_t d1;
    rtc_date_t d2;

    scanf("%d %d %d %d %d %d", &d1.year, &d1.month, &d1.day, &d2.year, &d2.month, &d2.day);

    int days = dday(d1, d2);

    printf("%04d/%02d/%02d - %04d/%02d/%02d --> %d days\n", d1.year, d1.month, d1.day, d2.year, d2.month, d2.day, days);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值