转换为 unix 时间戳不正确
我有一个我编写的函数(如果有一个好的标准替代品,请告诉我...)
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 }
,用于填充给定_time 结构。
我编写了一个函数来测试它,并准确地传递了该输入(纪元的开始)。但是,它返回的时间是 21600,即 1970-01-01 06:00:00,或 UTC+6。预期输出为 0(纪元的开始)。
注意:我所在的时区是美国中部时区,即 UTC - 6。1970 年 1 月 1 日午夜(CST),UTC 时间为 1970 年 1 月 1 日 06:00:00。
我的函数中是否有任何内容使其特定于我的时区?我在这个函数中做错了什么吗,或者我可以做一些不同的事情来使其独立于区域,或者至少始终是 UTC。
I have a function that I wrote (if there is a good standard substitute, please let me know...)
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);
}
The input (time_str) to the function is of the format 1970-01-01 00:00:00.0. The split_string() function splits the string time_str
into a vector containing:
{ 1970, 01, 01, 00, 00, 00 }
which is used to fill in the given_time structure.
I wrote a function to test it, and passed it exactly that input (start of epoch). However, the time it gives me back is 21600, which is 1970-01-01 06:00:00, or UTC+6. The expected output is 0 (start of the epoch).
Note: that I am in the US-Central time zone, which is UTC - 6. At midnight on 1st Jan 1970 CST, time @ UTC would be 1st Jan 1970 06:00:00.
Is there anything in my function that is making it specific to my timezone? Am I doing something wrong in this function, or can I do something different to make it zone independent, or at least always UTC.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您使用 glibc,则可以使用
timegm
函数,它是mktime
的一个版本,它始终将时间解释为位于GMT
时区。不幸的是,该函数的文档基本上指出它不能使用标准库调用来实现。所以除非你拥有它,否则你有点运气不好。If you are using glibc you have the
timegm
function at your disposal, which is a version ofmktime
that always interprets the time as if it were in theGMT
timezone. Unfortunately, the documentation for that function basically states that it cannot otherwise be implemented using standard library calls. So you're sort of out of luck unless you have it.mktime
采用本地时区的时间。因此,如果您传递1970-01-01 00:00:00当地时间,它会返回1970-01-01 06:00:00 UTC,因为它应该。作为替代方案,如果您使用 glibc,则可以调用 timegm。如果您不使用 glibc,则在调用 mktime 时,可以通过修改 TZ 环境变量来临时将本地时间更改为 UTC,如 timegm 手册页中所述:
此外,您对
localtime
的调用是不必要的,您可能应该设置given_time->tm_isdst
,以避免可能的夏令时问题。mktime
takes a time in the local time zone. So, if you pass it 1970-01-01 00:00:00 local time, it returns 1970-01-01 06:00:00 UTC, as it should.As an alternative, you can call timegm, if you're using glibc. If you're not using glibc, you temporarily change the local time to UTC when calling mktime by messing with the TZ environment variable, as described on the timegm manpage:
Also, your call to
localtime
is unnecessary, and you probably ought to setgiven_time->tm_isdst
, to avoid possible daylight savings time issues.也许您应该使用
gmtime
而不是time
来摆脱时区问题。编辑:
我真的不明白为什么你用当前时间填充结构,然后覆盖它的所有组件。为什么不只是:
另一个编辑:
呃,
mktime
也考虑当地时间。除了将时区区域设置设置为 UTC 之外,我不太确定如何解决此问题。Maybe you should use
gmtime
instead oftime
, to rid yourself of timezone issues.Edit:
I don't really understand why you fill the structure with the current time, then overwrite all its components. Why not just:
Another edit:
Ugh,
mktime
considers local time too. I'm not really sure how you can get around this other than setting your timezone locale to UTC.只需避免这些尴尬的函数并自己进行数学计算即可。 POSIX 指定
time_t
是自“纪元”(1970-01-01 00:00:00 GMT)以来以秒为形式的算术类型,没有任何闰秒废话(所有天都是 86400 日历秒,与SI秒相差很小),因此除了一点闰年逻辑之外,计算非常简单。像这样的日历计算是标准的入门编程练习,因此我相信您可以解决它或在网络上找到解决方案。
顺便说一句,也许 ISO C 和 POSIX 省略这样一个函数的原因是,与涉及时区的转换可以任意复杂并且只有主机的库可以在不同的应用程序之间可靠且一致地执行不同,GMT 转换是纯算术,没有外部参数。
Just avoid these awkward functions and do the math yourself. POSIX specifies that
time_t
is an arithmetic type in the form of seconds since "the epoch" (1970-01-01 00:00:00 GMT) without any leapsecond nonsense (all days are exactly 86400 calendar seconds, which differ from SI seconds by a tiny amount), so aside from a little leapyear logic, the computation is extremely straightforward.Calendar calculations like this are a standard introductory programming exercise so I'm sure you can work it out or find solutions on the web.
As an aside, perhaps the reason ISO C and POSIX omit such a function is that, unlike conversions involving timezones which can be arbitrarily complex and which only the host's library can perform reliably and consistently across different applications, GMT conversions are pure arithmetic with no external parameters.
当您调用 mktime 时,它会将参数解释为本地时间。
您还使用了“localtime”之类的功能,这些功能似乎没有用,我认为您可以放弃它们。
When you call mktime, it interpretes the parameter as a local time.
You have also used function like "localtime" that seems to be useless and I think you can drop them.
您可以围绕
strptime
编写一个包装器来进行解析。@Josh Kelley 的回答彻底解释了时区问题。
You could write a wrapper around
strptime
to do the parsing.@Josh Kelley's answer explains the timezone issue thoroughly.