小沃最近写代码遇到需要在单片机中使用时间与时间戳互转的需求,随即自己写了一个,使用方法尽可能的模仿linux c中的mktime与localtime函数,代码如下:
time.h
#ifndef __TIME_H__
#define __TIME_H__
struct tm {
int tm_year; // 年份,其值等于实际年份减去1900
int tm_mon; // 月份(从一月开始,0代表一月) - 取值区间为[0,11]
int tm_mday; // 一个月中的日期 - 取值区间为[1,31]
int tm_hour; // 时 - 取值区间为[0,23]
int tm_min; // 分 - 取值区间为[0,59]
int tm_sec; // 秒 – 取值区间为[0,59]
int tm_wday; // 一周中的第几天 – 取值区间为[0,6]
int tm_yday; // 一年中的第几天 – 取值区间为[0,365]
};
void localtime(unsigned long timestamp, struct tm *t);
unsigned long mktime(struct tm *t);
#endiftime.c
#include "time.h"
static unsigned int mon_yday[2][12] = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
};
static unsigned char isleap(unsigned int year) {
return (year%4==0 && year%100!=0) || (year%400==0) ? 1 : 0;
}
void localtime(unsigned long timestamp, struct tm *t) {
unsigned int year = 1970;
unsigned char mon = 0;
unsigned char leap;
unsigned char week = (timestamp%(7*24*3600))/(24*3600)+3;
if (week > 6) {
week -= 7;
}
t->tm_wday = week;
// 取秒时间
t->tm_sec = timestamp % 60;
timestamp /= 60;
// 取分钟时间
t->tm_min = timestamp % 60;
timestamp /= 60;
// 小时数
t->tm_hour = timestamp % 24;
timestamp /= 24;
// 计算年份
while (1) {
if (isleap(year)) {
if (timestamp < 366) {
break;
}
timestamp -= 366;
} else {
if (timestamp < 365) {
break;
}
timestamp -= 365;
}
year++;
}
t->tm_year = year-1900;
t->tm_yday = timestamp;
// 计算月分
leap = isleap(year);
for (mon = 0 ; mon < 12 ; mon++) {
if (timestamp < mon_yday[leap][mon]) {
break;
}
}
mon--;
timestamp -= mon_yday[leap][mon];
t->tm_mon = mon;
t->tm_mday = timestamp+1; // 日期取值为1到31
}
unsigned long mktime(struct tm *t) {
unsigned int i = 0;
// 以平年时间计算的秒数
unsigned int year = t->tm_year + 1900;
unsigned long result = (year - 1970)*365*24*3600 + (mon_yday[isleap(year)][t->tm_mon]+t->tm_mday-1)*24*3600 + t->tm_hour*3600 + t->tm_min*60 + t->tm_sec;
// 加上闰年的秒数
for (i = 1970; i < year; i++) {
if (isleap(i)) {
result += 24 * 3600;
}
}
return result;
}
/*
#include <stdio.h>
int main() {
// 测试1,时间转时间戳
struct tm t = {
2021 - 1900,
6 - 1,
24,
18,
58,
39
};
time_t timestamp = mktime(&t);
printf("timestamp:%u\n", timestamp);
// 测试2,时间戳转时间
struct tm t2;
localtime(1624536919, &t2);
printf("%d %d %d %d %d %d %d %d",
t2.tm_year, t2.tm_mon, t2.tm_mday, t2.tm_hour, t2.tm_min, t2.tm_sec, t2.tm_wday, t2.tm_yday);
return(0);
}
*/文章作者:沃航科技