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秒后轉為常用時間格式。