在C/C++中转换本地时间和GMT/UTC时间

32

如何在C/C++中在本地时间和UTC之间转换日期时间是最好的方法?

“日期时间”指包含日期和时间的时间表示。我可以使用time_tstruct tm或任何其他使其成为可能的表示。

我的平台是Linux。

这是我要解决的具体问题:我得到了一对包含儒略日和一天中的秒数的值。 这些值在GMT中。 我需要将其转换为本地时区的“YYYYMMDDHHMMSS”值。 我知道如何将儒略日转换为Y-M-D,并且显然很容易将秒转换为HHMMSS。 但是,棘手的部分是时区转换。 我相信我可以找到解决方案,但我更愿意找到一个“标准”或“众所周知”的方法,而不是摸索着解决问题。


可能相关的问题是在C中获取时区的夏令时转换日期

3个回答

24

你应该使用gmtime/localtimetimegm/mktime的组合。这将为您提供在struct tmtime_t之间进行转换的正交工具。

对于UTC/GMT:

time_t t;
struct tm tm;
struct tm * tmp;
...
t = timegm(&tm);
...
tmp = gmtime(t);

获取本地时间:

t = mktime(&tm);
...
tmp = localtime(t);

tzset() 的作用只是将内部时区变量从 TZ 环境变量中设置。我认为这不应该被调用多次。

如果您想在不同的时区之间进行转换,应该修改 struct tmtm_gmtoff


1
是的,不幸地,系统的设计者选择了本地时间作为消息协议的“标准”时间戳格式。当人们这样做时,我很讨厌它。 - Kristopher Johnson
4
在Windows中没有timegm函数。 - stepancheg
我很可能会将此作为一个单独的问题来问(现在正在查找提到tm_gmtoff的问题,而这个列表非常短),但是:你能否举个例子来修改tm_gmtoff并使其有用?当我这样做时,它似乎不会改变例如strftime(buf, BUFSIZ,“%FT%T%z(%+%z)”,tm)的输出。?? - lindes
似乎tm_gmtoff不是struct tm的标准成员。http://www.cplusplus.com/reference/clibrary/ctime/tm - Oscar
在Windows上,您可以使用_mkgmtime(&tm);,它将解释struct tm为UTC而不是当前时区。 - dash-tom-bang
显示剩余3条评论

19

如果你在Windows上,无法使用timegm()函数:

struct tm *tptr;
time_t secs, local_secs, gmt_secs;
time( &secs );  // Current time in GMT
// Remember that localtime/gmtime overwrite same location
tptr = localtime( &secs );
local_secs = mktime( tptr );
tptr = gmtime( &secs );
gmt_secs = mktime( tptr );
long diff_secs = long(local_secs - gmt_secs);

或类似的东西...


secsgmt_secs不应该是相同的吗?我认为你可以简化这个程序。 - jowo
1
我尝试过这个方法。我试图通过将结果与相反值进行测试来验证它。有时它有效,而有时它会差一个小时。我猜这是因为夏令时在我尝试的不同位置以不同的日期开始和结束(使用GMT,但针对PST本地时间进行转换)。是否有任何方法可以对此进行补偿? - Chris Westin
1
这个版本使用了Boost POSIX时间库,似乎可以在不同时区的夏令时日期不同的情况下正常工作:https://dev59.com/mm855IYBdhLWcg3wPBpx#6849810。 - Chris Westin

3

如果你需要担心转换带有时区规则的日期/时间,那么你可能需要了解ICU


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接