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
三 總結
本文主要講述如何獲取正確的系統時間,以及背後的原理,主要是和具體時區有關。
如果有寫的不對的地方,希望能留言指正,謝謝閱讀。