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

Posted

技术标签:

【中文标题】在 C/C++ 中在当地时间和 GMT/UTC 之间转换【英文标题】:Converting Between Local Times and GMT/UTC in C/C++ 【发布时间】:2010-10-20 04:39:02 【问题描述】:

在 C/C++ 中在本地时间和 UTC 之间转换日期时间的最佳方法是什么?

“日期时间”是指包含日期和时间的一些时间表示。我会很高兴time_tstruct tm 或任何其他使之成为可能的表示。

我的平台是 Linux。

这是我要解决的具体问题:我得到一对包含儒略日期和一天中的秒数的值。这些值在格林威治标准时间。我需要将其转换为本地时区“YYYYMMDDHHMMSS”值。我知道如何将儒略日期转换为 Y-M-D,显然很容易将秒转换为 HHMMSS。然而,棘手的部分是时区转换。我确信我可以找到解决方案,但我更愿意找到一种“标准”或“众所周知”的方式,而不是四处走动。


一个可能相关的问题是Get Daylight Saving Transition Dates For Time Zones in C

【问题讨论】:

【参考方案1】:

您应该使用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

【讨论】:

谢谢!我知道必须存在类似 timegm() 的东西,但不知道名称。 很高兴为您提供帮助。时间转换可能是一个相当棘手的领域。尽可能将所有内容存储在 UTC 中通常是个好主意。时区之间的转换更加棘手! 是的,不幸的是,系统的设计者选择了本地时间作为消息传递协议的“标准”时间戳格式。当人们这样做时,我讨厌它。 Windows 中没有timegm。 我可能会将此作为一个单独的问题提出(挖掘现在提到 tm_gmtoff 的问题,并且列表很短),但是:您能否举一个修改 tm_gmtoff 并具有那做点什么有用的?当我这样做时,它似乎并没有改变例如strftime(buf, BUFSIZ, "%FT%T%z (%+ %z)", tm); 的输出。 ??【参考方案2】:

如果在 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 相同吗?我认为您可以简化一下。 我试过这个。我试图通过逆向测试结果来验证它。在某些时候它可以工作,而对于其他人来说,它会关闭一个小时。我猜这是因为 DST 在我尝试的不同位置的不同日期开始和停止(使用 GMT,但转换为 PST 本地时间)。有什么办法可以弥补吗? 此版本使用 Boost POSIX 时间库,尽管不同时区的 DST 日期不同,但似乎可以正常工作:***.com/a/6849810/857029。【参考方案3】:

如果您需要担心使用时区规则转换日期/时间,您可能需要查看ICU。

【讨论】:

以上是关于在 C/C++ 中在当地时间和 GMT/UTC 之间转换的主要内容,如果未能解决你的问题,请参考以下文章

centos7之关于时间和日期以及时间同步的应用

强制 Java 时区为 GMT/UTC

在 PHP 中获取 UTC 时间

Unix 格式的 GMT/UTC(非本地)时间

如何获取 ISO-8601 GMT/UTC 年周数

Log4cpp:在 UTC/GMT 时区打印日期