1. 常用时间格式转时间戳
1 /* 2 * 输入UTC、GMT时,得到时间戳,Linux源代码 3 */ 4 uint32_t mktime (unsigned int year, unsigned int mon, 5 unsigned int day, unsigned int hour, 6 unsigned int min, unsigned int sec) 7 { 8 if (0 >= (int) (mon -= 2)){ /**//* 1..12 -> 11,12,1..10 */ 9 mon += 12; /**//* Puts Feb last since it has leap day */ 10 year -= 1; 11 } 12 13 return ((( 14 (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) + 15 year*365 - 719499 16 )*24 + hour /**//* now have hours */ 17 )*60 + min /**//* now have minutes */ 18 )*60 + sec; /**//* finally seconds */ 19 }
来源: 网络
2.时间戳转常用时间格式
1 /* 2 * 时间戳转换为普通时间 3 */ 4 void TimestampToNormalTime(struct RTC_DateTimeTypeDef *time, uint32_t Timestamp) 5 { 6 7 uint16_t year = 1970; 8 uint32_t Counter = 0, CounterTemp; //随着年份迭加,Counter记录从1970 年 1 月 1 日(00:00:00 GMT)到累加到的年份的最后一天的秒数 9 uint8_t Month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 10 uint8_t i; 11 12 while(Counter <= Timestamp) //假设今天为2018年某一天,则时间戳应小于等于1970-1-1 0:0:0 到 2018-12-31 23:59:59的总秒数 13 { 14 CounterTemp = Counter; //CounterTemp记录完全1970-1-1 0:0:0 到 2017-12-31 23:59:59的总秒数后退出循环 15 Counter += 31536000; //加上今年(平年)的秒数 16 if(IsLeapYear(year)) 17 { 18 Counter += 86400; //闰年多加一天 19 } 20 year++; 21 } 22 time->year = year - 1; //跳出循环即表示到达计数值当前年 23 Month[1] = (IsLeapYear(time->year)?29:28); 24 Counter = Timestamp - CounterTemp; //Counter = Timestamp - CounterTemp 记录2018年已走的总秒数 25 CounterTemp = Counter/86400; //CounterTemp = Counter/(24*3600) 记录2018年已【过去】天数 26 Counter -= CounterTemp*86400; //记录今天已走的总秒数 27 time->hour = Counter / 3600; //时 得到今天的小时 28 time->minute = Counter % 3600 / 60; //分 29 time->second = Counter % 60; //秒 30 for(i=0; i<12; i++) 31 { 32 if(CounterTemp < Month[i]) //不能包含相等的情况,相等会导致最后一天切换到下一个月第一天时 33 { //(即CounterTemp已走天数刚好为n个月完整天数相加时(31+28+31...)), 34 time->month = i + 1; // 月份不加1,日期溢出(如:出现32号) 35 time->date = CounterTemp + 1; //应不作处理,CounterTemp = Month[i] = 31时,会继续循环,月份加一, 36 break; //日期变为1,刚好符合实际日期 37 } 38 CounterTemp -= Month[i]; 39 } 40 getWEEK(time); 41 } 42 /* 43 * 判断闰年平年 44 */ 45 uint8_t IsLeapYear(uint16_t year) 46 { 47 if(((year)%4==0 && (year)%100!=0) || (year)%400==0) 48 return 1; //是闰年 49 return 0; //是平年 50 } 51 52 /* 53 * 函数功能:根据具体日期得到星期 54 * 吉姆拉尔森公式 week=(date+2*month+3*(month+1)/5+year+year/4-y/100+y/400)%7 55 * 注 : 把一月 二月看成是上一年的13 14月 , 得到结果 0 -- 6 56 */ 57 void getWEEK(struct RTC_DateTimeTypeDef *time) 58 { 59 u16 YY = 0; 60 u8 MM = 0; 61 if(time->month==1 || time->month==2) 62 { 63 MM = time->month + 12; 64 YY = time->year - 1; 65 }else{ 66 MM = time->month; 67 YY = time->year; 68 } 69 time->week = ( (time->date+2*MM+3*(MM+1)/5+YY+YY/4-YY/100+YY/400)%7 ) + 1; 70 } //(29 + 16 + 5 + 2018 +2018/4 - 2018/100 + 2018/400)%7 71 //(29 + 16 + 5 + 18 +18/4 - 18/100 + 18/400)%7
自己编写 暂未发现有bug
3.UTC转北京时间
1 /* 2 * UTC、GMT时间转换为北京时间 3 */ 4 void GMTtoBeijingTime(struct RTC_DateTimeTypeDef *GMTtime, struct RTC_DateTimeTypeDef *Beijingtime) 5 { 6 Beijingtime->year = GMTtime->year; 7 Beijingtime->month = GMTtime->month; 8 Beijingtime->date = GMTtime->date; 9 Beijingtime->hour = GMTtime->hour; 10 Beijingtime->minute = GMTtime->minute; 11 Beijingtime->second = GMTtime->second; 12 13 if(GMTtime->hour+8 > 23) //东八区已是第二天 14 { 15 Beijingtime->hour = GMTtime->hour + 8 - 24; //东八区真实时间(小时) 16 //大月 17 if((GMTtime->month==1)||(GMTtime->month==3)||(GMTtime->month==5)||(GMTtime->month==7)||(GMTtime->month==8)||(GMTtime->month==10)||(GMTtime->month==12)) 18 { 19 if(GMTtime->date==31) //如果此时UTC时是大月最后一天,则东八区当前时为下一月1号 20 { 21 Beijingtime->date = 1; 22 Beijingtime->month++; 23 if(Beijingtime->month > 12) ////如果此时UTC时是12月最后一天,则东八区当前时则为下一年1月1日 24 { 25 Beijingtime->month = 1; 26 Beijingtime->year++; 27 } 28 }else{ //如果此时UTC时不是大月最后一天 29 Beijingtime->date++; 30 } 31 } 32 //二月 33 else if(GMTtime->month==2) 34 { 35 if((IsLeapYear(GMTtime->year)==1&&GMTtime->date==28) || (GMTtime->date<28)) //如果UTC时是闰年,且UTC时为28号,则东八区现在为29号 或者 小于28号,则加一 36 { 37 Beijingtime->date++; 38 } 39 else if((IsLeapYear(GMTtime->year)==0&&Beijingtime->date==28) || (Beijingtime->date==29)) //如果UTC时是平年且UTC时为28号 或者 为29号,则东八区现在为3月1日 40 { 41 Beijingtime->date = 1; 42 Beijingtime->month++; 43 } 44 } 45 //小月 46 else 47 { 48 if(GMTtime->date==30) //如果此时UTC时是小月最后一天,则东八区当前时则为下一月1号 49 { 50 Beijingtime->date = 1; 51 Beijingtime->month++; 52 }else{ //如果此时UTC时不是小月最后一天 53 Beijingtime->date++; 54 } 55 } 56 }else{ //如果此时UTC时与东八区时同一天 57 Beijingtime->hour = GMTtime->hour + 8; 58 } 59 60 getWEEK(Beijingtime); 61 }
自己编写 暂未发现有bug
自动校时(GPS、WiFi)时,获得UTC时间,可直接转为北京时间存储(DS1302)。或UTC转时间戳存储(STM32F1),读出时间戳后加上 8*3600秒后转为常用时间格式。