mktime时间的转换

最近在分析一些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;
}

你可能感兴趣的:(C++,LInux,time)