STM32F103时间戳与常用时间格式互换算法


 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秒后转为常用时间格式。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM