我有一个我写的功能(如果有一个很好的标准替代品,请告诉我......)
time_t get_unix_time(string time_str) {
time_t loctime;
time(&loctime);
struct tm *given_time;
time_str = time_str.substr(0, time_str.find_first_of('.'));
replace(time_str.begin(), time_str.end(), ':', ',');
replace(time_str.begin(), time_str.end(), '-', ',');
replace(time_str.begin(), time_str.end(), '/', ',');
replace(time_str.begin(), time_str.end(), ' ', ',');
given_time = localtime(&loctime);
vector<string> trecord = split_string(time_str, ',');
given_time->tm_year = atoi(trecord.at(0).c_str()) - 1900;
given_time->tm_mon = atoi(trecord.at(1).c_str()) - 1;
given_time->tm_mday = atoi(trecord.at(2).c_str());
given_time->tm_hour = atoi(trecord.at(3).c_str());
given_time->tm_min = atoi(trecord.at(4).c_str());
given_time->tm_sec = atoi(trecord.at(5).c_str());
return mktime(given_time);
}
该函数的输入(time_str)格式为 1970-01-01 00:00:00.0 。 split_string()函数将字符串time_str
拆分为包含以下内容的向量:
{1970,01,01,00,00,00}
用于填充given_time结构。
我编写了一个测试它的函数,并将其完全传递给了输入(epoch的开始)。但是,它给我的时间是21600, 1970-01-01 06:00:00 ,或 UTC + 6 。预期输出为 0 (纪元的开始)。
注意:我在美国 - 中部时区,即UTC - 6.在1970年1月1日午夜CST,时间@ UTC将是1970年1月1日06:00:00。
我的功能中是否有任何特定于我的时区的内容?我在这个函数中做错了什么,或者我可以做一些不同的事情来使它区域独立,或者至少总是UTC。
答案 0 :(得分:5)
如果您使用的是glibc,则可以使用timegm
函数,这是mktime
的一个版本,它始终将时间解释为GMT
中的时间} 时区。不幸的是,该函数的文档基本上表明它不能使用标准库调用来实现。所以,除非你拥有它,否则你有点不幸。
答案 1 :(得分:4)
mktime
需要一段时间在当地时区。因此,如果您通过 1970-01-01 00:00:00当地时间,它将返回 1970-01-01 06:00:00 UTC ,因为它应该
作为替代方案,如果您使用的是glibc,则可以致电timegm。如果您没有使用glibc,则在通过弄乱TZ环境变量调用mktime时暂时将本地时间更改为UTC,如timegm联机帮助页中所述:
time_t my_timegm (struct tm *tm) {
time_t ret;
char *tz;
tz = getenv("TZ");
setenv("TZ", "", 1);
tzset();
ret = mktime(tm);
if (tz)
setenv("TZ", tz, 1);
else
unsetenv("TZ");
tzset();
return ret;
}
此外,您对[{1}}的调用是不必要的,您可能应该设置localtime
,以避免可能的夏令时问题。
答案 2 :(得分:1)
也许您应该使用gmtime
代替time
来摆脱时区问题。
修改强> 我真的不明白为什么用当前时间填充结构,然后覆盖它的所有组件。为什么不呢:
time_t get_unix_time(const string& time_str)
{
vector<string> trecord = split_string(time_str, ',');
tm given_time;
given_time.tm_year = atoi(trecord.at(0).c_str()) - 1900;
given_time.tm_mon = atoi(trecord.at(1).c_str()) - 1;
given_time.tm_mday = atoi(trecord.at(2).c_str());
given_time.tm_hour = atoi(trecord.at(3).c_str());
given_time.tm_min = atoi(trecord.at(4).c_str());
given_time.tm_sec = atoi(trecord.at(5).c_str());
return mktime(&given_time);
}
另一个编辑:
呃,mktime
也考虑当地时间。除了将您的时区区域设置为UTC之外,我不确定如何解决此问题。
答案 3 :(得分:1)
避免这些尴尬的功能并自己做数学。 POSIX指定time_t
是自“the epoch”(1970-01-01 00:00:00 GMT)以来的秒数形式的算术类型,没有任何leapsecond废话(所有日子都是86400 日历秒,与 SI秒相差很小一些),所以除了一点点的误差之外,计算非常简单。
这样的日历计算是一个标准的入门编程练习,所以我相信你可以解决它或在网上找到解决方案。
顺便说一下,ISO C和POSIX省略这样一个功能的原因可能是,与涉及时区的转换不同,时区可以是任意复杂的,并且只有主机库可以在不同的应用程序中可靠且一致地执行,GMT转换是纯算术没有外部参数。
答案 4 :(得分:0)
当您调用mktime时,它会将参数解释为本地时间。 你还使用了像“本地时间”这样似乎毫无用处的功能,我想你可以放弃它们。
答案 5 :(得分:0)
您可以在strptime
周围编写一个包装来进行解析。
struct tm given_time;
strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &given_time);
return mktime(&given_time);
@Josh Kelley的回答彻底解释了时区问题。