8位单片机可用的 mktime localtime函数
8位单片机可用的 mktime localtime函数及源码
最近在做一个8位单片机项目,其中用到了时间戳转换函数,这个在32位机上一个库函数就解决了问题,没想到在8位单片机中没有对应库(time.h),没有办法只有自己来写。
目标:1,满足和库函数mktime localtime所计算出的数据一至;2,考虑8位单片机的处理能力慢软件效率问题。
分享给大家,方便有同样需求的朋友。
gcc 环境进行测试:
测试程序:
1 #include <stdio.h> 2 #include <stdint.h> 3 #include <time.h> 4 #include <string.h> 5 6 #if 0 7 struct tm { 8 int tm_sec; /* seconds after the minute, 0 to 60 9 (0 - 60 allows for the occasional leap second) */ 10 int tm_min; /* minutes after the hour, 0 to 59 */ 11 int tm_hour; /* hours since midnight, 0 to 23 */ 12 int tm_mday; /* day of the month, 1 to 31 */ 13 int tm_mon; /* months since January, 0 to 11 */ 14 int tm_year; /* years since 1900 */ 15 // int tm_wday; /* days since Sunday, 0 to 6 */ 16 // int tm_yday; /* days since January 1, 0 to 365 */ 17 // int tm_isdst; /* Daylight Savings Time flag */ 18 }; 19 #endif 20 static const char mon_list[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 21 static const char leap_mon_list[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 22 23 /******************************************************************************* 24 * Function Name : fun_mktime 25 * Description : 时间转为时间戳 26 * Input : 27 * Output : 28 * Other : 29 * Date : 2016.11.14 30 *******************************************************************************/ 31 int32_t fun_mktime(struct tm *pT) 32 { 33 const char *pDays = NULL; 34 int32_t tmp = 0; 35 int16_t i = 0; 36 37 //计算总共有多少个闰年 38 tmp = (pT->tm_year / 4 - pT->tm_year / 100 + pT->tm_year / 400) - (1970 / 4 - 1970 / 100 + 1970 / 400); 39 40 //如果当年是闰年,需要减去当年的闰年 41 if ((pT->tm_year % 4 == 0) && ((pT->tm_year % 100 != 0) || (pT->tm_year % 400 == 0))) 42 { 43 tmp = tmp - 1 + (pT->tm_year - 1970) * 365; 44 pDays = leap_mon_list; 45 } 46 else 47 { 48 tmp = tmp + (pT->tm_year - 1970) * 365; 49 pDays = mon_list; 50 } 51 52 for (i = 0; i < pT->tm_mon - 1; i++) 53 tmp += pDays[i]; 54 55 tmp = tmp + pT->tm_mday - 1; 56 57 tmp = tmp * 24 + pT->tm_hour; 58 59 tmp = tmp * 60 + pT->tm_min; 60 61 tmp = tmp * 60 + pT->tm_sec; 62 63 return tmp; 64 } 65 66 /******************************************************************************* 67 * Function Name : fun_localtime 68 * Description : 时间戳转为时间 69 * Input : struct tm *pT: 输出的时间缓冲区 uint32_t tim:当前时间戳 70 * Output : 71 * Other : 72 * Date : 2016.11.14 73 *******************************************************************************/ 74 void fun_localtime(struct tm *pT, int32_t tim) 75 { 76 const char *pDays = NULL; 77 78 uint16_t index = 0; 79 80 memset(pT, 0, sizeof(*pT)); 81 82 //year initialization 83 if (tim > 0x5685C180L) // 2016-1-1 0:0:0 84 { 85 pT->tm_year = 2016; 86 tim -= 0x5685C180L; 87 } 88 else if (tim > 0x4B3D3B00L) // 2010-1-1 0:0:0 89 { 90 pT->tm_year = 2010; 91 tim -= 0x4B3D3B00L; 92 } 93 else if (tim > 0x386D4380L) // 2000-1-1 0:0:0 94 { 95 pT->tm_year = 2000; 96 tim -= 0x386D4380L; 97 } 98 else 99 { 100 pT->tm_year = 1970; 101 } 102 103 //now have year 104 while (tim >= 366L * 24 * 60 * 60) 105 { 106 if ((pT->tm_year % 4 == 0) && ((pT->tm_year % 100 != 0) || (pT->tm_year % 400 == 0))) 107 tim -= 366L * 24 * 60 * 60; 108 else 109 tim -= 365L * 24 * 60 * 60; 110 111 pT->tm_year++; 112 } 113 114 // then 365 * 24 * 60 * 60 < tim < 366 * 24 * 60 * 60 115 if (!(((pT->tm_year % 4 == 0) && ((pT->tm_year % 100 != 0) || (pT->tm_year % 400 == 0)))) 116 && (tim > 365L * 24 * 60 * 60)) 117 { 118 tim -= 365L * 24 * 60 * 60; 119 pT->tm_year++; 120 } 121 122 // this year is a leap year? 123 if (((pT->tm_year % 4 == 0) && ((pT->tm_year % 100 != 0) || (pT->tm_year % 400 == 0)))) 124 pDays = leap_mon_list; 125 else 126 pDays = mon_list; 127 128 pT->tm_mon = 1; 129 // now have mon 130 while (tim > pDays[index] * 24L * 60 * 60) 131 { 132 tim -= pDays[index] * 24L * 60 * 60; 133 index++; 134 pT->tm_mon++; 135 } 136 137 // now have days 138 pT->tm_mday = tim / (24L * 60 * 60) + 1; 139 tim = tim % (24L * 60 * 60); 140 141 // now have hour 142 pT->tm_hour = tim / (60 * 60); 143 tim = tim % (60 * 60); 144 145 // now have min 146 pT->tm_min = tim / 60; 147 tim = tim % 60; 148 149 pT->tm_sec = tim; 150 } 151 152 153 int main (void *parg) 154 { 155 struct tm *pT = {0}; 156 time_t timep = 0; 157 uint32_t cur_tim = 0; 158 159 time(&timep); 160 161 pT = localtime(&timep); 162 163 printf("linux time \t= %d\n", (int32_t)timep); 164 pT->tm_year += 1900; 165 pT->tm_mon += 1; 166 printf("fun_mktime \t= %d\n", cur_tim = (uint32_t)fun_mktime(pT)); 167 168 printf("localtime \t= %d-%d-%d %d:%d:%d\n", pT->tm_year, pT->tm_mon, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec); 169 memset(pT, 0, sizeof(*pT)); 170 fun_localtime(pT, cur_tim); 171 printf("fun_localtime \t= %d-%d-%d %d:%d:%d\n", pT->tm_year, pT->tm_mon, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec); 172 return 0; 173 }
测试结果:
linux time = 1480133002 fun_mktime = 1480161802 localtime = 2016-11-26 12:3:22 fun_localtime = 2016-11-26 12:3:22
linux time 是库函数mktime计算结果,因为进行了时区处理,所以与fun_mktime计算出来刚好是8 * 3600 秒的差值
此函数在C51下进行过测试,符合要求。