今天遇到个问题,需求如题所示,本来以为直接用time.h提供的各个函数可以解决,但是折腾了半天发现不太可行,只有当地时间转UTC的。而tm结构体转time_t类型的mktime函数又自带时区属性。所以写下博客,让大家以后可以参考参考此方法。
主要是利用gmtime_r和localtime_r手动计算时区差异,使用int类型,保证可正可负。
系统调用较多,效率可能较低,或者可以不获取此时时间,利用utcStrBuf的信息,来计算本地时间和对应UTC时间,得到差值,这样localtime_r可以少调用一次
#include <stdio.h>
#include <time.h>
#include <string.h>
int main()
{
// 需要求得此时间对应的时区时间
char utcStrBuf[] = "2021/12/27_22:30:20.369";
char localStrBuf[30]={0};
printf("utcStrBuf = %s\n",utcStrBuf);
// 计算时区差值
time_t now = time(NULL);
struct tm utcTm;
struct tm locTm;
memset(&utcTm,0,sizeof(utcTm));
memset(&locTm,0,sizeof(locTm));
gmtime_r(&now,&utcTm);
localtime_r(&now,&locTm);
int dTime = difftime(mktime(&locTm),mktime(&utcTm));
/*
struct tm {
int tm_sec; // Seconds (0-60)
int tm_min; // Minutes (0-59)
int tm_hour; // Hours (0-23)
int tm_mday; // Day of the month (1-31)
int tm_mon; // Month (0-11)
int tm_year; // Year - 1900
int tm_wday; // Day of the week (0-6, Sunday = 0)
int tm_yday; // Day in the year (0-365, 1 Jan = 0)
int tm_isdst; // Daylight saving time
};
*/
memset(&utcTm,0,sizeof(utcTm));
memset(&locTm,0,sizeof(locTm));
// 根据utcStr得到utc的tm结构体
int milliseconds = 0; // tm结构体没有毫秒信息,保存起来
sscanf(utcStrBuf,"%d/%d/%d_%d:%d:%d.%d",&(utcTm.tm_year),&(utcTm.tm_mon),&(utcTm.tm_mday),&(utcTm.tm_hour),&(utcTm.tm_min),&(utcTm.tm_sec),&milliseconds);
utcTm.tm_mon -=1;
utcTm.tm_year -=1900;
time_t locTime = mktime(&utcTm) + dTime;
localtime_r(&locTime,&locTm);
//snprintf(localStrBuf,30,"%d/%d/%d_%d:%d:%d.%d",locTm.tm_year+1900,locTm.tm_mon+1,locTm.tm_mday,locTm.tm_hour,locTm.tm_min,locTm.tm_sec,milliseconds);
char tmStr[25] = {0};
strftime(tmStr,25,"%Y/%m/%e_%H:%M:%S", &locTm);//以年月日_时分秒的形式表示当前时间
snprintf(localStrBuf,30,"%s.%d",tmStr,milliseconds);
printf("localStrBuf = %s\n",localStrBuf);
return 0;
}