client和server进行通信时,有时会要求获取server的系统时间,如用来查看某一事件发生的具体时间。
在之前的系列文章中获取系统时间一直用的是UA_DateTime_now(),这个API获取的时间是UTC时间,即世界协调时间,而我们身处中国,其具体时间为:
中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。
PS:这个8是指8小时
下面首先让我们看下UTC时间的打印表现,以及如何获取正确的系统时间。
下面是server.c代码,
#include "open62541.h"
#include
#include
UA_Boolean running = true;
static void stopHandler(int sign) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
running = false;
}
static void cycleCallback(UA_Server *server, void *data)
{
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ctrl callback");
UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now());
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec);
}
int main(void)
{
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_Server_addRepeatedCallback(server, cycleCallback, NULL, 2000, NULL); // call every 2s
UA_StatusCode retval = UA_Server_run(server, &running);
UA_Server_delete(server);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
代码里每隔2s会调用一次函数cycleCallback(),函数里会打印UA_DateTime_now()得到的时间,最终打印如下,
左侧是函数UA_LOG_INFO()打印log时带出的时间,这个时间是和真实的系统时间是一样的,右边打印的是UA_DateTime_now()得到的时间,可以看到差了8个小时。
open62541提供了一个API用来计算server所在时区相对UTC的偏移,即UA_DateTime_localTimeUtcOffset()
我们重新调整一下cycleCallback(),改为如下,
static void ctrlCallback(UA_Server *server, void *data)
{
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ctrl callback");
UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
// 打印这个偏移值
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "offset: %lld", tOffset);
// UA_DateTime_now()加上偏移值,得到正确的系统时间
UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec);
}
打印如下,
可以看到现在得到的是正确的时间了,可以和自己电脑上的时间比对一下,也是一致的。
这个偏移值打印出来是288000000000,为什么是这个值呢?前面说了中国的时区是UTC+8,即偏移8个小时,8个小时换算成秒就8 x 60 x 60 = 28800
,而open62541内部计算时间用的最小单位是1/10微秒,那么就再乘以10000000,就得到288000000000
本文主要讲述如何获取正确的系统时间,以及背后的原理,主要是和具体时区有关。
如果有写的不对的地方,希望能留言指正,谢谢阅读。