在我的系统中,我有一台PC(Linux,以防万一),它使RTC时间保持UTC时间,从而使我的本地时区成为特定时间。在PC代码中,我从使用纪元以来的秒数获取UTC时间
struct timespec tv;
clock_gettime(CLOCK_REALTIME, &tv);
double time = (tv.tv_nsec / 1000000000.0) + tv.tv_sec;
return time;
我还有一个第三方网络设备,它也提供从纪元开始的秒数,但它使用的是本地时间而不是UTC时间。这是一个问题,因为当我在交错日志中用PC和此设备的时间戳打印两个时间戳时,即使两个时钟显示的是相同的本地时间,该时间戳也已关闭。
让我们假设PC和此设备之间的时区设置(UTC偏移量和夏令时规范)相同。我将如何处理自设备提供的时间(本地时间)以来的秒数,并将其转换为UTC的时间点以来的秒数?换句话说,以编程方式(以C方式)将PC时区设置应用到自该时间点到当前时间的秒数是什么?
这是我尝试将自纪元以来的第三方设备基于本地时间的秒数转换为自纪元以来的基于UTC的秒数。
#include <stdio.h>
#include <time.h>
int main(void)
{
// The following epoch timestamps were converted to human time via https://www.epochconverter.com/
time_t device_rawtime = 1568133906.065000; // if treated as GMT: Tuesday, September 10, 2019 4:45:06.065 PM
time_t pc_rawtime = 1568151907.454432; // if treated as localtime: Tuesday, September 10, 2019 4:45:07.454 PM GMT-05:00 DST
struct tm ts;
char buf[80];
ts = *gmtime(&device_rawtime);
strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
time_t converted = mktime(&ts);
printf("Device rawtime=%ld which is PC localtime %s ==> UTC based rawtime=%ld (pc was %ld)\n", device_rawtime, buf, converted, pc_rawtime);
return 0;
}
以上操作无效。它打印
Device rawtime=1568133906 which is PC localtime Tue 2019-09-10 16:45:06 GMT ==> UTC based rawtime=1568155506 (pc was 1568151907)
如您所见,转换后的设备时间戳不等于PC时间戳。应该怎么做?
答案 0 :(得分:1)
我同意这很可能是由于夏令时。但是问题是我应该如何解释呢?
相关信息可在man mktime
中找到:
在 tm_isdst 字段中指定的值通知 mktime ()是否 对于 tm 结构中提供的时间,夏令时(DST)是否有效:正值表示DST有效;零表示DST 无效;负值表示 mktime ()应该(使用时区信息和系统数据库)尝试确定DST是否为 在指定时间生效。
从gmtime(&device_rawtime)
返回时,ts.tm_isdst设置为零,因为gmtime()
采取的UTC永远不会夏令时。因此,当调用mktime(&ts)
时,它会使用 DST无效的信息来转换时间结构,因此我们得到的转换后的时间值太高了3600秒。要正确考虑DST,请设置
ts.tm_isdst = -1
在调用mktime(&ts)
之前就足够了。