美文网首页
RTC 时间问题

RTC 时间问题

作者: wjundong | 来源:发表于2022-05-19 19:51 被阅读0次
/**
 * 思路是循环累加两个相差的年份, 然后再减去较小年份的日期走过多少天, 加上较大年份的日期走过多少天
 * 
 * 比如 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;
}

相关文章

  • RTC 时间问题

  • RTC驱动分析

    学号:19021211263 linux中的rtc驱动位于drivers/rtc下,里面包含了许多开发平台的RTC...

  • 2018-05Stm23L151C8t6低功耗模式RTC唤醒失败

    问题描述: stm32L151使用RTC唤醒来退出stop模式,RTC运行但不能唤醒 RTC唤醒成功后,进入sto...

  • webrtc入门实战,粘去就行

    用一个html页面实现2个rtc通道连接,用户A(rtc) 给 用户B(rtc2)发视频看,展示用户A的视频 效果...

  • RTC

    [RK3128][Android 6.0] RTC设备注册及调用流程 [RK3128][Android 6.0] ...

  • RTC

    下面的程序根据固件库进行修改,变成自己想要的程序,包含RTC秒中断以及闹钟中断,由于嵌入式竞赛板没有外加晶振,所以...

  • RTC

    2016年实时互联网行业飞速发展。连麦互动直播迅速渗透垂直行业;狼人杀、Houseparty爆红带来的全新社交模式...

  • RTC 相关

    RTC 是一个独立的定时器,能够在 STM32 的低功耗模式下运行。 选择 RTC 时钟源 RTC 时钟的时钟源能...

  • STM32CubeMX学习笔记(14)——RTC实时时钟使用

    一、RTC简介 实时时钟(RTC) 是一个独立的 BCD 定时器/计数器。 RTC 提供具有可编程闹钟中断功能的日...

  • 10.25嵌入式知识点总结

    1.RTC 实时时钟 BCD 二进码十进制格式 2.RTC具有自动唤醒功能 3.RTC模块和时钟配置是在后备区...

网友评论

      本文标题:RTC 时间问题

      本文链接:https://www.haomeiwen.com/subject/sgztprtx.html