2017-03-02 78 views
0

我写了下面的代码将日期转换为时间戳。转换日期为时代忽略系统时区

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 

int main() 
{ 
    struct tm date_time; 
    char date_time_buf[255]; 
    char date_time_hdr[255]={0}; 
    strncpy(date_time_hdr,"Thu, 02 Mar 2017 05:54:28 GMT",255); 
    memset(&date_time, 0, sizeof(struct tm)); 
    strptime(date_time_hdr, "%a, %d %b %Y %H:%M:%S %Z", &date_time); 
    memset(date_time_buf, 0, 255); 
    strftime(date_time_buf, 255, "%s", &date_time); 
    int p=atoi(date_time_buf); 
    printf("time is %d \r\n", p); 
    return 0; 
} 

我可以将日期转换为时间戳。但面临一个问题。 时间戳由5小时30分钟偏移,这是我的Linux机器的时区。但我不想那样。有没有办法忽略系统时区?

+0

由于您使用的是POSIX.1 ['strptime()'](http://man7.org/linux/man-pages/man3/strptime.3.html),您应该添加'posix'标签对你的问题! –

回答

0

而不是使用strftime()格式化分解时间struct tm为一个整数,并使用atoi()解析它,你可以使用简单,但非标准timegm()功能。

尽管timegm()不在POSIX中,但它由大多数POSIXy系统提供。如果你希望你的代码是跨POSIXy系统携带方便,你可以用一种变通方法(如timegm男人页面的某些版本的描述):

#define _POSIX_C_SOURCE 200809L 
#define _XOPEN_SOURCE 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include <errno.h> 

time_t alt_timegm(struct tm *from) 
{ 
    char *tz; 
    time_t result; 
    int  saved_errno; 

    tz = getenv("TZ"); 
    if (tz) 
     tz = strdup(tz); 

    setenv("TZ", "", 1); /* TZ empty refers to UTC */ 
    tzset(); 

    errno = 0; 
    result = mktime(from); 
    saved_errno = errno; 

    setenv("TZ", tz, 1); 
    free(tz); 

    errno = saved_errno; 
    return result; 
} 

这种解决方法确实有其临时修改当前时区的缺点,这会影响执行任何时区相关函数的其他线程。在单线程的过程中,这不是问题(因为与时区相关的功能不是异步信号安全的,所以它们不能用于信号处理程序)。

在多线程程序中,一个应该序列的所有访问在时区相关的功能 - alt_timegm()以上,mktime()localtime(),等等 - ,以保证每个功能与适当的时区设置运行。

Linux和BSD中的timegm()实现是线程安全的;也就是说,他们不会修改时区。

使用上述,解析使用strptime()格式到Unix时间戳的字符串是容易的:

const char *parse_utc(const char *s, const char *format, time_t *to) 
{ 
    char  *result; 
    struct tm t_parts; 
    time_t  t; 

    if (!s || !format) { 
     errno = EINVAL; 
     return NULL; 
    } 

    result = strptime(s, format, &t_parts); 
    if (!result) { 
     errno = EINVAL; 
     return NULL; 
    } 

    errno = 0; 
    t = alt_timegm(&t_parts); 
    if (to) 
     *to = result; 

    return (const char *)result; 
} 

上面parse_utc()解析串s使用strptime()格式format,节约了UTC时间戳to如果不为NULL,将指针返回字符串s中的第一个未解析的字符。

设置在上述功能errno = 0可能看起来很奇怪,但它是因为mktime()(和timegm())函数可以或可以不在发生错误的情况下设置errno;它只是返回(time_t)-1。这意味着无法可靠地确定(time_t)-1(对应于UTC的1969年的最后一秒)是否是实际的有效时间戳或错误返回。

换句话说,如果errno != 0在致电parse_utc()后出现错误。 (请注意,如果字符串或格式无效,parse_utc()返回NULL,与errno == EINVAL。)如果errno == 0*to == (time_t)-1,它取决于体系结构时间字符串是否实际上指UTC时间1969年的最后一秒,或者它是否是错误;我们根本不知道。