最近在分析一些log的时候需要进行时间的处理,log中的时间格式是这样的:"05/Jan/2015:16:12:15"。由于需要计算两个时间的差值,所以将其转换成数字进行处理会比较方便。
于是先解析这个字符串,提取相应的字段,然后用mktime转换成time_t。结果在ubuntu上测试没问题,在android上却出现计算出来的时间比输入的时间少了3600s。
原来是需要把struct tm中的tm_isdst设置成0。这个字段对于北京时间来说应该程序中主动设为0, 否则系统可能把它设成1,造成偏差。
另外,北京时间比UTC/GMT时间早8个小时: http://www.worldtimeserver.com/current_time_in_CN.aspx
time(NULL)得到的是UTC时间,但是如果你把转换成localtime,再转换成UTC时间,就会发现两者差28800s,即8小时。
下面是一些验证性代码以供参考:
#include
#include
#include
#include
#include
struct tm parseTime(const char* ts)
{
// Format like "05/Jan/2015:16:12:15 +0800"
printf("timeFromString:%s\n", ts);
const char *Monthes[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly", "Aug", "Sep", "Oct", "Nov", "Dec"};
const int DAY_IDX = 0;
const int MON_IDX = 1;
const int YEAR_IDX = 2;
const int HOUR_IDX = 3;
const int MIN_IDX = 4;
const int SEC_IDX = 5;
const int intervals[6] = {3, 4, 5, 3, 3, 3};
int vals[6];
char buf[5];
for (int i=0; i<6; ++i)
{
//snprintf(buf, intervals[i], "%s", ts);
strncpy(buf, ts, intervals[i]-1);
buf[intervals[i]-1] = '\0';
ts += intervals[i];
if (i == 1)
{
for (int j=1; j<=12; ++j)
{
if (!strncmp(buf, Monthes[j-1], 3))
{
vals[i] = j;
break;
}
}
}
else
{
vals[i] = atoi(buf);
}
//printf("buf:%s, %d\n", buf, vals[i]);
}
struct tm y2k;
y2k.tm_year = vals[YEAR_IDX] - 1900;
y2k.tm_mon = vals[MON_IDX] - 1 ;
y2k.tm_mday = vals[DAY_IDX];
y2k.tm_hour = vals[HOUR_IDX];
y2k.tm_min = vals[MIN_IDX];
y2k.tm_sec = vals[SEC_IDX];;
y2k.tm_isdst = 0; // important for Chinese time! no dst!
return y2k;
}
time_t localTimeFromString(const char* ts)
{
struct tm y2k = parseTime(ts);
return mktime(&y2k);
}
time_t localTimeToUTC(const char* ts)
{
time_t result;
struct tm y2k = parseTime(ts);
#if 0
result = mktime(&y2k) - timezone;
printf("timezone:%ld\n", timezone);
//printf("mktime:%ld\n", result);
#else
char *oldTZ = getenv("TZ");
putenv("TZ=UTC");
tzset();
result = mktime(&y2k);
//printf("mktime:%ld\n", result);
printf("timezone:%ld\n", timezone);
if(oldTZ == NULL)
{
putenv("TZ=");
}
else
{
char buf[256];
sprintf(buf, "TZ=%s", oldTZ);
putenv(buf);
}
tzset();
#endif
return result;
}
int formatTime(time_t t, char *buf, int maxsize)
{
const char* format = "%d/%b/%Y:%H:%M:%S\n";
struct tm *tmp;
tmp = localtime(&t);
if (tmp == NULL)
{
perror("localtime");
return -1;
}
if (strftime(buf, maxsize, format, tmp) == 0) {
fprintf(stderr, "strftime returned 0");
return -1;
}
return 0;
}
int main ()
{
time_t now = time(NULL);
char buf[256] = {0};
formatTime(now, buf, 256);
printf("formatedString:%s\n", buf);
time_t nt = localTimeFromString(buf);
printf("oldtime:%ld\nnewtime:%ld\n", now, nt);
const char *s = "01/Jan/1970:00:00:00";
time_t utcT = localTimeToUTC(s);
printf("timer: %ld, utcT:%ld\n", time(NULL), utcT);
utcT = localTimeToUTC(buf);
printf("now: %ld\nutcT:%ld\ndiff:%f\n", now, utcT, difftime(utcT, now));
return 0;
}