自定义UTC时间转换

#ifndef __UTC_CONVERT_H
#define __UTC_CONVERT_H

#include "stdint.h"

#define BASE_YEAR   1970   /* 基于1970-1-1 0:0:0 */

typedef uint32_t utc_sec;
typedef struct utc_time_t
{
    uint16_t year;  /* 实际年份,不需要额外 + 1970 */
    uint8_t mon;    /* 实际月份,不需要额外 + 1 */
    uint8_t day;
    uint8_t min;
    uint8_t hour;
    uint8_t sec;
} utc_time_t;

void utc_to_time(utc_sec utc, utc_time_t *tm);
utc_sec time_to_utc(utc_time_t *tm);

#endif // __UTC_CONVERT_H
#include "utc_convert.h"

static const uint8_t days_per_mon[2][12] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
};

#define SEC_PER_DAY          86400UL
#define IsLeapYear(yr)       (!((yr) % 400) || (((yr) % 100) && !((yr) % 4)))
#define DAYS_PER_YEAR(yr)    (IsLeapYear(yr) ? 366 : 365)
#define DAYS_PER_MON(yr, mh) (IsLeapYear(yr) ? days_per_mon[1][mh] : days_per_mon[0][mh])

/*****************************************************************
 * @brief UTC转换为年月日时分秒
 * 
 * @param[in] utc UTC时间
 * @param[out] tm RTC时间
 ****************************************************************/
void utc_to_time(utc_sec utc, utc_time_t *tm)
{
    uint32_t day = utc % SEC_PER_DAY;
    uint32_t days = utc / SEC_PER_DAY;

    tm->sec = day % 60UL;
    tm->min = (day % 3600UL) / 60UL;
    tm->hour = day / 3600UL;
    /* year */
    tm->year = BASE_YEAR;
    while (days >= DAYS_PER_YEAR(tm->year))
    {
        days -= DAYS_PER_YEAR(tm->year);
        tm->year++;
    }
    /* month */
    tm->mon = 0;
    while (days >= DAYS_PER_MON(tm->year, tm->mon))
    {
        days -= DAYS_PER_MON(tm->year, tm->mon);
        tm->mon++;
    }
    /* day */
    tm->day = days;

    tm->mon++;
    tm->day++;
}

/*****************************************************************
 * @brief 年月日时分秒转换为UTC时间
 * 
 * @param tm RTC时间
 * @return UTC时间
 ****************************************************************/
utc_sec time_to_utc(utc_time_t *tm)
{
    uint32_t seconds = (((tm->hour * 60UL) + tm->min) * 60UL) + tm->sec;
    uint16_t year = tm->year;
    int8_t month = tm->mon;
    uint16_t days = tm->day;

    month--;
    days--;

    while (--month >= 0)
    {
        days += DAYS_PER_MON(tm->year, month);
    }

    while (--year >= BASE_YEAR)
    {
        days += DAYS_PER_YEAR(year);
    }

    seconds += (days * SEC_PER_DAY);

    return seconds;
}
posted @ 2022-03-11 11:11  Bryce-Hu  阅读(213)  评论(0)    收藏  举报