学习open62541 --- [32] 正确获取系统时间

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()得到的时间,最终打印如下,
学习open62541 --- [32] 正确获取系统时间_第1张图片
左侧是函数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);
}

打印如下,
学习open62541 --- [32] 正确获取系统时间_第2张图片
可以看到现在得到的是正确的时间了,可以和自己电脑上的时间比对一下,也是一致的。

这个偏移值打印出来是288000000000,为什么是这个值呢?前面说了中国的时区是UTC+8,即偏移8个小时,8个小时换算成秒就8 x 60 x 60 = 28800,而open62541内部计算时间用的最小单位是1/10微秒,那么就再乘以10000000,就得到288000000000


三 总结

本文主要讲述如何获取正确的系统时间,以及背后的原理,主要是和具体时区有关。

如果有写的不对的地方,希望能留言指正,谢谢阅读。

你可能感兴趣的:(open62541,C/C++)