學習open62541 --- [32] 正確獲取系統時間

client和server進行通信時,有時會要求獲取server的系統時間,如用來查看某一事件發生的具體時間。

在之前的系列文章中獲取系統時間一直用的是UA_DateTime_now(),這個API獲取的時間是UTC時間,即世界協調時間,而我們身處中國,其具體時間爲:

中國大陸、中國香港、中國澳門、中國臺灣、蒙古國、新加坡、馬來西亞、菲律賓、西澳大利亞州的時間與UTC的時差均爲+8,也就是UTC+8。

PS:這個8是指8小時

下面首先讓我們看下UTC時間的打印表現,以及如何獲取正確的系統時間。


一 現象

下面是server.c代碼,

#include "open62541.h"

#include <signal.h>
#include <stdlib.h>

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


三 總結

本文主要講述如何獲取正確的系統時間,以及背後的原理,主要是和具體時區有關。

如果有寫的不對的地方,希望能留言指正,謝謝閱讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章