时间戳与时间转换

此文档里代码源自 mynewt 工程源码下 time/Datetime/src/Datetime.c

 

润年天数为366,平年天数365。判断为润年:当前年份能被4整除且不能被100整除 或者 可被400整除的

#define days_in_year(y)     (leapyear(y) ? 366 : 365)

/*
 * This inline avoids some unnecessary modulo operations
 * as compared with the usual macro:
 *   ( ((year % 4) == 0 &&
 *      (year % 100) != 0) ||
 *     ((year % 400) == 0) )
 * It is otherwise equivalent.
 */
static int
leapyear(int year)
{
    int rv = 0;

    if ((year & 3) == 0) {
        rv = 1;
        if ((year % 100) == 0) {
            rv = 0;
            if ((year % 400) == 0)
                rv = 1;
        }
    }
    return (rv);
}

 

每月对应的天数,润年时2月份为29天,平年为28天

#define    FEBRUARY    2
#define days_in_month(y, m) \
    (month_days[(m) - 1] + (m == FEBRUARY ? leapyear(y) : 0))

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

 

对于当前时间点,不同时间对应的时间点不同。

#define POSIX_BASE_YEAR 1970
#define SECDAY  (24 * 60 * 60)

struct clocktime {
    int year;   /* year (4 digit year) */
    int mon;    /* month (1 - 12) */
    int day;    /* day (1 - 31) */
    int hour;   /* hour (0 - 23) */
    int min;    /* minute (0 - 59) */
    int sec;    /* second (0 - 59) */
};

/** Structure representing a timezone offset */
struct timezone {
    /** Minutes west of GMT */
    short tz_minuteswest;
    /** Daylight savings time correction (if any) */
    short tz_dsttime;
};

struct ctimeval {
    /* Seconds */
    unsigned long tv_sec;    
};

 

时间转换成时间戳函数

int
clocktime_to_timeval(const struct clocktime *ct, const struct timezone *tz, struct ctimeval *tv)
{
    int i, year, days;

    year = ct->year;

    /* Sanity checks. */
    if (year < POSIX_BASE_YEAR ||
        ct->mon < 1 || ct->mon > 12 ||
        ct->day < 1 || ct->day > days_in_month(year, ct->mon) ||
        ct->hour < 0 || ct->hour > 23 ||
        ct->min < 0 || ct->min > 59 ||
        ct->sec < 0 || ct->sec > 59) {
        return -1;
    }

    /*
     * Compute days since start of time
     * First from years, then from months.
     */
    days = 0;
    for (i = POSIX_BASE_YEAR; i < year; i++)
        days += days_in_year(i);

    /* Months */
    for (i = 1; i < ct->mon; i++)
          days += days_in_month(year, i);
    days += (ct->day - 1);

    tv->tv_sec = (((int64_t)days * 24 + ct->hour) * 60 + ct->min) * 60 +
        ct->sec;


    /* Convert localtime to utctime */
    if (tz != NULL) {
    tv->tv_sec += tz->tz_minuteswest * 60;
    tv->tv_sec -= tz->tz_dsttime ? 3600 : 0;
    }
    
    return (0);
}

 

时间戳转换成对应时间函数 

int
timeval_to_clocktime(const struct ctimeval *tv, const struct timezone *tz,
    struct clocktime *ct)
{
    int i, year, days;
    unsigned long rsec;           /* remainder seconds */
    unsigned long secs;

    secs = tv->tv_sec;
    if (tz != NULL) {
        /* Convert utctime to localtime */
        secs -= tz->tz_minuteswest * 60;
        secs += tz->tz_dsttime ? 3600 : 0;
    }


    days = secs / SECDAY;
    rsec = secs % SECDAY;

    /* Subtract out whole years, counting them in i. */
    for (year = POSIX_BASE_YEAR; days >= days_in_year(year); year++)
        days -= days_in_year(year);
    ct->year = year;

    /* Subtract out whole months, counting them in i. */
    for (i = 1; days >= days_in_month(year, i); i++)
        days -= days_in_month(year, i);
    ct->mon = i;

    /* Days are what is left over (+1) from all that. */
    ct->day = days + 1;

    /* Hours, minutes, seconds are easy */
    ct->hour = rsec / 3600;
    rsec = rsec % 3600;
    ct->min  = rsec / 60;
    rsec = rsec % 60;
    ct->sec  = rsec;

    return (0);
}

 

测试函数,以北京时间2019-12-25 14:45:32 为例

int main(void){
    
    struct ctimeval gtimeval = {0};
    struct clocktime time = {
        2019,12,25,
        14,45,32
    };
    struct timezone localzone= {-480, 0};/* 北京时间,东8区 */
    
    int ret = 0;
            
    ret = clocktime_to_timeval(&time, &localzone, &gtimeval);
    if(!ret){        
        printf("Sec:%ld\n", gtimeval.tv_sec);
    }
    
    memset(&time, 0, sizeof(struct clocktime));
    ret = timeval_to_clocktime(&gtimeval, &localzone, &time);
    if(!ret){
        printf("Date:%ld-%ld-%ld %ld:%ld:%ld\r\n",
                time.year, time.mon, time.day,
                time.hour, time.min, time.sec);
    }    
}

 

执行后的结果,与网络工具计算结果 相同

 

 

  

 

代码路径:https://files.cnblogs.com/files/T0213-ZH/Datetime.rar

posted @ 2019-12-25 15:26  不在+年华  阅读(593)  评论(0编辑  收藏  举报