时间戳与时间转换
此文档里代码源自 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, >imeval); if(!ret){ printf("Sec:%ld\n", gtimeval.tv_sec); } memset(&time, 0, sizeof(struct clocktime)); ret = timeval_to_clocktime(>imeval, &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