STM32开发 -- UTC、UNIX时间戳、北京时间之间的转换

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29350001/article/details/87637350

我碰到的问题,GPS上UTC时间转北京时间和STM32上UNIX时间戳转北京时间。
这部分之前讲RTC和GPS的时候有涉及到一部分。
具体的RTC如何得到UNIX时间戳,和GNRMC如何解析得到UTC时间可以参看一下。
参看:STM32开发 – RTC详解
参看:STM32开发 – GPS模块开发详解

扩展:C语言再学习 – 时间函数

这里主要看三者转换方法:

一、UTC时间转换为北京时间

参看:UTC时间转换为北京时间

时间类型结构体

//UTC时间信息
__packed typedef struct  
{										    
 	uint16_t year;	//年份
	uint8_t month;	//月份
	uint8_t date;	//日期
	uint8_t hour; 	//小时
	uint8_t min; 	//分钟
	uint8_t sec; 	//秒钟
}nmea_time;

UTC时间转任意时区时间

其中,北京时间 = UTC time + 8 hours

void UTC_to_BJtime(nmea_time*	utc_time, int8_t	timezone)
{
	int year,month,day,hour;
    int lastday = 0;					//last day of this month
    int lastlastday = 0;			//last day of last month

    year	 = utc_time->year;			 //utc time
    month  = utc_time->month;
    day 	 = utc_time->date;
    hour 	 = utc_time->hour + timezone; 
	
    if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
        lastday = 31;
        if(month == 3){
            if((year%400 == 0)||(year%4 == 0 && year%100 != 0))				//if this is lunar year
                lastlastday = 29;
            else
                lastlastday = 28;
        }
        if(month == 8)
            lastlastday = 31;
    }
    else if(month == 4 || month == 6 || month == 9 || month == 11){
        lastday = 30;
        lastlastday = 31;
    }
    else{
        lastlastday = 31;
        if((year%400 == 0)||(year%4 == 0 && year%100 != 0))
            lastday = 29;
        else
            lastday = 28;
    }

    if(hour >= 24){					// if >24, day+1
            hour -= 24;
            day += 1; 

            if(day > lastday){ 		// next month,  day-lastday of this month
                day -= lastday;
                month += 1;

                if(month > 12){		//	next year , month-12
                    month -= 12;
                    year += 1;
                }
            }
        }
    if(hour < 0){										// if <0, day-1
            hour += 24;
            day -= 1; 
            if(day < 1){					  // month-1, day=last day of last month
                day = lastlastday;
                month -= 1;
                if(month < 1){ 			// last year , month=12
                    month = 12;
                    year -= 1;
                }
            }
        }
   // transfer value to NMEA_result.local_time
	NMEA_result.local_time.year  = year;
	NMEA_result.local_time.month = month;
	NMEA_result.local_time.date  = day;
	NMEA_result.local_time.hour  = hour;
	NMEA_result.local_time.min	 = utc_time->min;
	NMEA_result.local_time.sec	 = utc_time->sec;
}

二、UNIX Time 时间戳 与 北京时间 相互转换

参看:UNIX Time 时间戳 与 北京时间 相互转换

typedef struct t_xtime {
  int year; int month;  int day;  
  int hour; int minute;  int second;
} _xtime ;
 
#define xMINUTE   (60             ) //1分的秒数
#define xHOUR      (60*xMINUTE) //1小时的秒数
#define xDAY        (24*xHOUR   ) //1天的秒数
#define xYEAR       (365*xDAY   ) //1年的秒数

1、将localtime(UTC+8北京时间)转为UNIX TIME,以1970年1月1日为起点

unsigned int  xDate2Seconds(_xtime *time)
{
  static unsigned int  month[12]={
    /*01月*/xDAY*(0),
    /*02月*/xDAY*(31),
    /*03月*/xDAY*(31+28),
    /*04月*/xDAY*(31+28+31),
    /*05月*/xDAY*(31+28+31+30),
    /*06月*/xDAY*(31+28+31+30+31),
    /*07月*/xDAY*(31+28+31+30+31+30),
    /*08月*/xDAY*(31+28+31+30+31+30+31),
    /*09月*/xDAY*(31+28+31+30+31+30+31+31),
    /*10月*/xDAY*(31+28+31+30+31+30+31+31+30),
    /*11月*/xDAY*(31+28+31+30+31+30+31+31+30+31),
    /*12月*/xDAY*(31+28+31+30+31+30+31+31+30+31+30)
  };
  unsigned int  seconds = 0;
  unsigned int  year = 0;
  year = time->year-1970;       //不考虑2100年千年虫问题
  seconds = xYEAR*year + xDAY*((year+1)/4);  //前几年过去的秒数
  seconds += month[time->month-1];      //加上今年本月过去的秒数
  if( (time->month > 2) && (((year+2)%4)==0) )//2008年为闰年
    seconds += xDAY;            //闰年加1天秒数
  seconds += xDAY*(time->day-1);         //加上本天过去的秒数
  seconds += xHOUR*time->hour;           //加上本小时过去的秒数
  seconds += xMINUTE*time->minute;       //加上本分钟过去的秒数
  seconds += time->second;               //加上当前秒数<br> seconds -= 8 * xHOUR;
  return seconds;
}

2、将UNIX时间转为UTC+8 即北京时间

//UNIX转为UTC 已进行时区转换 北京时间UTC+8
void xSeconds2Date(unsigned long seconds,_xtime *time )
{
    static unsigned int month[12]={
        /*01月*/31, 
        /*02月*/28, 
        /*03月*/31, 
        /*04月*/30, 
        /*05月*/31, 
        /*06月*/30, 
        /*07月*/31, 
        /*08月*/31, 
        /*09月*/30, 
        /*10月*/31, 
        /*11月*/30, 
        /*12月*/31 
    };
    unsigned int days; 
    unsigned short leap_y_count; 
    time->second      = seconds % 60;//获得秒 
    seconds          /= 60; 
    time->minute      =  seconds % 60;//获得分 
    seconds          += 8 * 60 ;        //时区矫正 转为UTC+8 bylzs
    seconds          /= 60; 
    time->hour        = seconds % 24;//获得时 
    days              = seconds / 24;//获得总天数 
    leap_y_count = (days + 365) / 1461;//过去了多少个闰年(4年一闰) 
    if( ((days + 366) % 1461) == 0) 
    {//闰年的最后1天 
        time->year = 1970 + (days / 366);//获得年 
        time->month = 12;              //调整月 
        time->day = 31; 
        return; 
    } 
    days -= leap_y_count; 
    time->year = 1970 + (days / 365);     //获得年 
    days %= 365;                       //今年的第几天 
    days = 01 + days;                  //1日开始 
    if( (time->year % 4) == 0 ) 
    { 
        if(days > 60)--days;            //闰年调整 
        else 
        { 
            if(days == 60) 
            { 
                time->month = 2; 
                time->day = 29; 
                return; 
            } 
        } 
    } 
    for(time->month = 0;month[time->month] < days;time->month++) 
    { 
        days -= month[time->month]; 
    } 
    ++time->month;               //调整月 
    time->day = days;           //获得日 
}

3、UTC(字符串)转UNIX时间

/*******************************************************************************
* Function Name  : ConvertTimeToSecond
* Description    : Convert GPS Date to Log buffer.
* Input          : @date: format 'DDMMYY,HHMMSS.SSS'
* Output         : None
* Return         : Sencod
*******************************************************************************/
static u32 ConvertDateToSecond(const u8 *date)
{
	u32 sencods = 0;
	u16 temp = 1970;
	u16 days = 0;
	if(NULL == date) {
		return 0;
	}
	//year
	temp = (date[4] - 0x30) * 10 + (date[5] - 0x30) + 2000;
	if(0 == (temp % 4)) {
		days += 1;
	}
	temp -= 1;
	//UTC time start 1970
	for(; temp >= 1970; temp--) {
		if(temp % 4) {
			days += 365;
		} else {
			//leap year
			days += 366;
		}
	}
	//month
	temp = (date[2] - 0x30) * 10 + (date[3] - 0x30);
	temp -= 1;
	for(; temp >= 1; temp--) {
		days += months[temp];
	}
	//day
	temp = (date[0] - 0x30) * 10 + (date[1] - 0x30);
	days += temp - 1;
	//hour
	temp = (date[7] - 0x30) * 10 + (date[8] - 0x30);
	sencods += temp * ONEMINUTETOSENCOND;
	//min
	temp = (date[9] - 0x30) * 10 + (date[10] - 0x30);
	sencods += temp * 60;
	//sencod
	temp = (date[11] - 0x30) * 10 + (date[12] - 0x30);
	sencods += temp;

	sencods += days * ONEDAYTOSENCOND;

	return sencods;
}

猜你喜欢

转载自blog.csdn.net/qq_29350001/article/details/87637350
今日推荐