RTC 时间问题
2022-05-19 本文已影响0人
wjundong
/**
* 思路是循环累加两个相差的年份, 然后再减去较小年份的日期走过多少天, 加上较大年份的日期走过多少天
*
* 比如 2000/04/05-2002/05/02
*
* |----------+---/--------------------------------------|----------+---/
* 2000 4 5 2002 5 2
*
* [----------------for 循环年得到的天数------------------]
* [-减去走过的天数-] [-加上走过的天数-]
* [----------------------最终天数-----------------------]
*
*/
#include <stdio.h>
#include <stdint.h>
static inline int is_leap_year(unsigned int year)
{
return (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0));
}
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t weekday;
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
}rtc_time_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_time_t date1, rtc_time_t date2)
{
rtc_time_t *dmax = date1.year > date2.year ? &date1 : &date2;
rtc_time_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;
}
/* rtc 时间转为秒, 即计算时间 t 相对 base_year 年1月1日 00:00:00 走过的秒数 */
uint32_t rtc2sec(int base_year, const rtc_time_t *t)
{
int days = 0;
/* 从基准年算起, 到 t - 1 年所累加的天数 */
for (int y = base_year; y < t->year; y++)
days += is_leap_year(y) ? 366 : 365;
/* 再加上 t 这一年已经走过的整月的天数 */
int leap = is_leap_year(t->year);
for (int m = 1; m < t->month; m++)
days += month_days[leap][m - 1];
days += t->day - 1;
return days*24*3600 + t->hours*3600 + t->minutes*60 + t->seconds;
}
/* 秒数转为 rtc 时间, 即计算 base_year 年1月1日 00:00:00 后经过 sec 秒的时间 t */
void sec2rtc(uint16_t base_year, uint32_t sec, rtc_time_t *t)
{
/* 可分成多少整天 */
int days = sec / (24*3600);
/* 剩余不到 1 天的秒数 */
int rem = sec % (24*3600);
int tmp = 0;
/* 从基准年开始, 所剩天数大于当前年的天数, 对年进行累加并减去天数 */
for (t->year = base_year; ( tmp = (is_leap_year(t->year) ? 366 : 365) ) && days >= tmp; t->year++)
days -= tmp;
/* 从1月开始, 所剩天数大于当前月的天数, 对月进行累加并减去天数 */
for (t->month = 1; ( tmp = month_days[is_leap_year(t->year)][t->month - 1] ) && days >= tmp; t->month++)
days -= tmp;
t->day = days + 1;
t->hours = rem / 3600 % 100;
t->minutes = rem / 60 % 60;
t->seconds = rem % 60;
}
/* 返回时间 t 相对时间 base 走过了多少秒 */
uint32_t rtc2sec_base(const rtc_time_t *base, rtc_time_t *t)
{
return rtc2sec(base->year, t) - rtc2sec(base->year, base);
}
/* 返回在时间 base 的基础上加 sec 秒得到时间 t */
void sec2rtc_base(const rtc_time_t *base, uint32_t sec, rtc_time_t *t)
{
sec2rtc(base->year, rtc2sec(base->year, base) + sec, t);
}
rtc_time_t base = {
.year = 1970,
.month = 1,
.day = 1,
.hours = 8,
.minutes = 0,
.seconds = 0,
};
rtc_time_t d1 = {
.year = 2022,
.month = 12,
.day = 31,
.hours = 23,
.minutes = 59,
.seconds = 31,
};
void time_print(rtc_time_t *t)
{
printf("%04d-%02d-%02d %02d:%02d:%02d\n", t->year, t->month, t->day, t->hours, t->minutes, t->seconds);
}
void rtc_time_add(rtc_time_t *t, uint32_t sec)
{
sec2rtc_base(t, sec, t);
// sec2rtc(t->year, sec, t);
}
/* 测试 */
int main(int argc, char const *argv[])
{
rtc_time_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);
uint32_t sec = rtc2sec_base(&base, &d1);
printf("sec %d\n", sec);
sec2rtc_base(&base, sec, &d2);
time_print(&d2);
rtc_time_add(&d2, 59);
time_print(&d2);
return 0;
}