c语言utc时间转换北京时间_STM32开发 -- UTC、UNIX时间戳、北京时间之间的转换
我遇到的问题是关于如何将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_ttimezone)
{
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 = xYEARyear + 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; //加上当前秒数
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;

[1] [2]

