我已编写以下代码将日期转换为时间戳。
#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 :(得分:0)
您可以使用简单但非标准的timegm()
函数,而不是使用strftime()
将细分时间struct tm
格式化为整数,并使用atoi()
进行解析。
即使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()
使用strptime()格式s
解析字符串format
,如果不是NULL则将UTC时间戳保存为to
,将指针返回到第一个未解析的字符串s
中的字符。
在上述函数中设置errno = 0
可能看起来很奇怪,但这是因为mktime()
(和timegm()
)函数可能会或可能不会设置{{ 1}}如果出错;它只返回errno
。这意味着无法可靠地确定(time_t)-1
(对应于UTC中1969年的最后一秒)是实际有效时间戳还是错误返回。
换句话说,如果在调用(time_t)-1
后errno != 0
,则会出现错误。 (请注意,如果字符串或格式无效,parse_utc()
会返回parse_utc()
,NULL
。)如果errno == EINVAL
但是errno == 0
,则取决于架构是否时间字符串实际上是指UTC中1969年的最后一秒,或者是否是错误;我们根本就不知道。