Browse Source

simplify datetime handling.

Julius Pfrommer 6 years ago
parent
commit
e74b4bf832

+ 3 - 3
examples/client_connect_loop.c

@@ -81,9 +81,9 @@ int main(void) {
         if (retval == UA_STATUSCODE_GOOD &&
             UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) {
             UA_DateTime raw_date = *(UA_DateTime *) value.data;
-            UA_String string_date = UA_DateTime_toString(raw_date);
-            UA_LOG_INFO(logger, UA_LOGCATEGORY_CLIENT, "string date is: %.*s", (int) string_date.length, string_date.data);
-            UA_String_deleteMembers(&string_date);
+            UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
+            UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
+                        dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
         }
         UA_Variant_deleteMembers(&value);
         UA_sleep_ms(1000);

+ 8 - 9
examples/tutorial_client_firststeps.c

@@ -25,16 +25,15 @@ int main(void) {
     UA_Variant_init(&value);
 
     /* NodeId of the variable holding the current time */
-    const UA_NodeId nodeId =
-        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
-
+    const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
     retval = UA_Client_readValueAttribute(client, nodeId, &value);
-    if(retval == UA_STATUSCODE_GOOD &&
-       UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) {
-        UA_DateTime raw_date = *(UA_DateTime*)value.data;
-        UA_String string_date = UA_DateTime_toString(raw_date);
-        printf("string date is: %.*s\n", (int)string_date.length, string_date.data);
-        UA_String_deleteMembers(&string_date);
+
+    if (retval == UA_STATUSCODE_GOOD &&
+        UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) {
+        UA_DateTime raw_date = *(UA_DateTime *) value.data;
+        UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
+        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
+                    dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
     }
 
     /* Clean up */

+ 50 - 24
include/ua_types.h

@@ -169,36 +169,30 @@ UA_STRING(char *chars) {
  * DateTime
  * ^^^^^^^^
  * An instance in time. A DateTime value is encoded as a 64-bit signed integer
- * which represents the number of 100 nanosecond intervals since January 1, 1601 */
-typedef int64_t UA_DateTime;
-
-/* Multiply to convert units for time difference computations */
-#define UA_USEC_TO_DATETIME 10LL
-#define UA_MSEC_TO_DATETIME (UA_USEC_TO_DATETIME * 1000LL)
-#define UA_SEC_TO_DATETIME (UA_MSEC_TO_DATETIME * 1000LL)
-#define UA_DATETIME_TO_USEC (1/10.0)
-#define UA_DATETIME_TO_MSEC (UA_DATETIME_TO_USEC / 1000.0)
-#define UA_DATETIME_TO_SEC (UA_DATETIME_TO_MSEC / 1000.0)
-
-/* Datetime of 1 Jan 1970 00:00 */
-#define UA_DATETIME_UNIX_EPOCH (11644473600LL * UA_SEC_TO_DATETIME)
+ * which represents the number of 100 nanosecond intervals since January 1, 1601
+ * (UTC).
+ *
+ * The methods providing an interface to the system clock are provided by a
+ * "plugin" that is statically linked with the library. */
 
-/* Diff between local time and UTC time */
-UA_DateTime UA_DateTime_diffLocalTimeUTC(void);
+typedef int64_t UA_DateTime;
 
-/* The current time in UTC time*/
-UA_DateTime UA_EXPORT UA_DateTime_nowUtcTime(void);
+/* Multiples to convert durations to DateTime */
+#define UA_DATETIME_USEC 10LL
+#define UA_DATETIME_MSEC (UA_DATETIME_USEC * 1000LL)
+#define UA_DATETIME_SEC (UA_DATETIME_MSEC * 1000LL)
 
-/* The current time in local time*/
-UA_DateTime UA_EXPORT UA_DateTime_nowLocalTime(void);
+/* The current time in UTC time */
+UA_DateTime UA_EXPORT UA_DateTime_now(void);
 
-/* Compatibility macro. Should be remove in the future */
-#define UA_DateTime_now() UA_DateTime_nowUtcTime()
+/* Offset between local time and UTC time */
+UA_Int64 UA_EXPORT UA_DateTime_localTimeUtcOffset(void);
 
-/* CPU clock invariant to system time changes. Use only for time diffs, not
- * current time */
+/* CPU clock invariant to system time changes. Use only to measure durations,
+ * not absolute time. */
 UA_DateTime UA_EXPORT UA_DateTime_nowMonotonic(void);
 
+/* Represents a Datetime as a structure */
 typedef struct UA_DateTimeStruct {
     UA_UInt16 nanoSec;
     UA_UInt16 microSec;
@@ -213,7 +207,23 @@ typedef struct UA_DateTimeStruct {
 
 UA_DateTimeStruct UA_EXPORT UA_DateTime_toStruct(UA_DateTime t);
 
-UA_String UA_EXPORT UA_DateTime_toString(UA_DateTime t);
+/* The C99 standard (7.23.1) says: "The range and precision of times
+ * representable in clock_t and time_t are implementation-defined." On most
+ * systems, time_t is a 4 or 8 byte integer counting seconds since the UTC Unix
+ * epoch. The following methods are used for conversion. */
+
+/* Datetime of 1 Jan 1970 00:00 */
+#define UA_DATETIME_UNIX_EPOCH (11644473600LL * UA_DATETIME_SEC)
+
+static UA_INLINE UA_Int64
+UA_DateTime_toUnixTime(UA_DateTime date) {
+    return (date - UA_DATETIME_UNIX_EPOCH) / UA_DATETIME_SEC;
+}
+
+static UA_INLINE UA_DateTime
+UA_DateTime_fromUnixTime(UA_Int64 unixDate) {
+    return (unixDate * UA_DATETIME_SEC) + UA_DATETIME_UNIX_EPOCH;
+}
 
 /**
  * Guid
@@ -928,6 +938,22 @@ UA_StatusCode_explanation(UA_StatusCode code) {
     return statusCodeExplanation_default.name;
 }
 
+UA_DEPRECATED UA_String
+UA_DateTime_toString(UA_DateTime t);
+
+/* The old DateTime conversion macros */
+UA_DEPRECATED static UA_INLINE double
+deprecatedDateTimeMultiple(double multiple) {
+    return multiple;
+}
+
+#define UA_USEC_TO_DATETIME deprecatedDateTimeMultiple((UA_Double)UA_DATETIME_USEC)
+#define UA_MSEC_TO_DATETIME deprecatedDateTimeMultiple((UA_Double)UA_DATETIME_MSEC)
+#define UA_SEC_TO_DATETIME deprecatedDateTimeMultiple((UA_Double)UA_DATETIME_SEC)
+#define UA_DATETIME_TO_USEC deprecatedDateTimeMultiple(1.0 / ((UA_Double)UA_DATETIME_USEC))
+#define UA_DATETIME_TO_MSEC deprecatedDateTimeMultiple(1.0 / ((UA_Double)UA_DATETIME_MSEC))
+#define UA_DATETIME_TO_SEC deprecatedDateTimeMultiple(1.0 / ((UA_Double)UA_DATETIME_SEC))
+
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 9 - 13
plugins/ua_clock.c

@@ -40,7 +40,7 @@
 
 #include "ua_types.h"
 
-UA_DateTime UA_DateTime_nowUtcTime(void) {
+UA_DateTime UA_DateTime_now(void) {
 #if defined(_WIN32)
     /* Windows filetime has the same definition as UA_DateTime */
     FILETIME ft;
@@ -54,12 +54,12 @@ UA_DateTime UA_DateTime_nowUtcTime(void) {
 #else
     struct timeval tv;
     gettimeofday(&tv, NULL);
-    return (tv.tv_sec * UA_SEC_TO_DATETIME) + (tv.tv_usec * UA_USEC_TO_DATETIME) + UA_DATETIME_UNIX_EPOCH;
+    return (tv.tv_sec * UA_DATETIME_SEC) + (tv.tv_usec * UA_DATETIME_USEC) + UA_DATETIME_UNIX_EPOCH;
 #endif
 }
 
-/* credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
-UA_DateTime UA_DateTime_diffLocalTimeUTC(void) {
+/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
+UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
     time_t gmt, rawtime = time(NULL);
 
 #ifdef _WIN32
@@ -77,11 +77,7 @@ UA_DateTime UA_DateTime_diffLocalTimeUTC(void) {
     gmt = mktime(ptm);
 #endif
 
-    return (UA_DateTime) ((int)difftime(rawtime, gmt) * UA_SEC_TO_DATETIME);
-}
-
-UA_DateTime UA_DateTime_nowLocalTime(void) {
-    return UA_DateTime_now() + UA_DateTime_diffLocalTimeUTC();
+    return (UA_Int64) (difftime(rawtime, gmt) * UA_DATETIME_SEC);
 }
 
 UA_DateTime UA_DateTime_nowMonotonic(void) {
@@ -89,7 +85,7 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
     LARGE_INTEGER freq, ticks;
     QueryPerformanceFrequency(&freq);
     QueryPerformanceCounter(&ticks);
-    UA_Double ticks2dt = UA_SEC_TO_DATETIME / (UA_Double)freq.QuadPart;
+    UA_Double ticks2dt = UA_DATETIME_SEC / (UA_Double)freq.QuadPart;
     return (UA_DateTime)(ticks.QuadPart * ticks2dt);
 #elif defined(__APPLE__) || defined(__MACH__)
     /* OS X does not have clock_gettime, use clock_get_time */
@@ -98,14 +94,14 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
     host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
     clock_get_time(cclock, &mts);
     mach_port_deallocate(mach_task_self(), cclock);
-    return (mts.tv_sec * UA_SEC_TO_DATETIME) + (mts.tv_nsec / 100);
+    return (mts.tv_sec * UA_DATETIME_SEC) + (mts.tv_nsec / 100);
 #elif !defined(CLOCK_MONOTONIC_RAW)
     struct timespec ts;
     clock_gettime(CLOCK_MONOTONIC, &ts);
-    return (ts.tv_sec * UA_SEC_TO_DATETIME) + (ts.tv_nsec / 100);
+    return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
 #else
     struct timespec ts;
     clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
-    return (ts.tv_sec * UA_SEC_TO_DATETIME) + (ts.tv_nsec / 100);
+    return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
 #endif
 }

+ 8 - 4
plugins/ua_log_stdout.c

@@ -2,7 +2,6 @@
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
 
 #include <stdio.h>
-#include <stdarg.h>
 #include "ua_log_stdout.h"
 #include "ua_types_generated.h"
 #include "ua_types_generated_handling.h"
@@ -47,16 +46,21 @@ __attribute__((__format__(__printf__, 3 , 0)))
 void
 UA_Log_Stdout(UA_LogLevel level, UA_LogCategory category,
               const char *msg, va_list args) {
-    UA_String t = UA_DateTime_toString(UA_DateTime_nowLocalTime());
+    UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
+    UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
+
 #ifdef UA_ENABLE_MULTITHREADING
     pthread_mutex_lock(&printf_mutex);
 #endif
-    printf("[%.23s (UTC%+.1f)] %s/%s" ANSI_COLOR_RESET "\t", t.data, (float)(UA_DateTime_diffLocalTimeUTC() / UA_SEC_TO_DATETIME)/3600.0, logLevelNames[level], logCategoryNames[category]);
+
+    printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s" ANSI_COLOR_RESET "\t",
+           dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec,
+           (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[level], logCategoryNames[category]);
     vprintf(msg, args);
     printf("\n");
     fflush(stdout);
+
 #ifdef UA_ENABLE_MULTITHREADING
     pthread_mutex_unlock(&printf_mutex);
 #endif
-    UA_ByteString_deleteMembers(&t);
 }

+ 15 - 19
plugins/ua_network_tcp.c

@@ -567,7 +567,7 @@ ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
     UA_DateTime now = UA_DateTime_nowMonotonic();
     LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
         if ((e->connection.state == UA_CONNECTION_OPENING) &&
-            (now > (e->connection.openingDate + (NOHELLOTIMEOUT * UA_MSEC_TO_DATETIME)))){
+            (now > (e->connection.openingDate + (NOHELLOTIMEOUT * UA_DATETIME_MSEC)))){
             UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
                         "Connection %i | Closed by the server (no Hello Message)",
                          e->connection.sockfd);
@@ -753,9 +753,8 @@ UA_ClientConnectionTCP(UA_ConnectionConfig conf,
         return connection;
     }
 
-
     UA_Boolean connected = UA_FALSE;
-
+    UA_DateTime dtTimeout = timeout * UA_DATETIME_MSEC;
     UA_DateTime connStart = UA_DateTime_nowMonotonic();
     SOCKET clientsockfd;
 
@@ -763,8 +762,8 @@ UA_ClientConnectionTCP(UA_ConnectionConfig conf,
      * want to try to connect. So use a loop and retry until timeout is
      * reached. */
     do {
-
         connection.state = UA_CONNECTION_OPENING;
+
         /* Get a socket */
         clientsockfd = socket(server->ai_family,
                               server->ai_socktype,
@@ -774,9 +773,8 @@ UA_ClientConnectionTCP(UA_ConnectionConfig conf,
     #else
         if(clientsockfd < 0) {
     #endif
-            UA_LOG_SOCKET_ERRNO_WRAP(
-                    UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
-                                          "Could not create client socket: %s", errno_str));
+            UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
+                                                    "Could not create client socket: %s", errno_str));
             freeaddrinfo(server);
             return connection;
         }
@@ -794,8 +792,7 @@ UA_ClientConnectionTCP(UA_ConnectionConfig conf,
         }
 
         /* Non blocking connect */
-        error = connect(clientsockfd, server->ai_addr,
-                        WIN32_INT server->ai_addrlen);
+        error = connect(clientsockfd, server->ai_addr, WIN32_INT server->ai_addrlen);
 
         if ((error == -1) && (errno__ != ERR_CONNECTION_PROGRESS)) {
             ClientNetworkLayerTCP_close(&connection);
@@ -810,25 +807,23 @@ UA_ClientConnectionTCP(UA_ConnectionConfig conf,
         /* Use select to wait and check if connected */
         if (error == -1 && (errno__ == ERR_CONNECTION_PROGRESS)) {
             /* connection in progress. Wait until connected using select */
-            UA_UInt32 timeSinceStart = (UA_UInt32)
-                ((UA_Double)(UA_DateTime_nowMonotonic() - connStart) * UA_DATETIME_TO_MSEC);
-            if(timeSinceStart > timeout)
+            UA_DateTime timeSinceStart = UA_DateTime_nowMonotonic() - connStart;
+            if(timeSinceStart > dtTimeout)
                 break;
 
             fd_set fdset;
             FD_ZERO(&fdset);
             UA_fd_set(clientsockfd, &fdset);
-            UA_UInt32 timeout_usec = (timeout - timeSinceStart) * 1000;
+            UA_DateTime timeout_usec = (dtTimeout - timeSinceStart) / UA_DATETIME_USEC;
             struct timeval tmptv = {(long int) (timeout_usec / 1000000),
                                     (long int) (timeout_usec % 1000000)};
 
-            int resultsize = select((UA_Int32)(clientsockfd + 1), NULL, &fdset,
-                                    NULL, &tmptv);
+            int resultsize = select((UA_Int32)(clientsockfd + 1), NULL, &fdset, NULL, &tmptv);
 
-            if (resultsize == 1) {
+            if(resultsize == 1) {
+#ifdef _WIN32
                 /* Windows does not have any getsockopt equivalent and it is not
                  * needed there */
-#ifdef _WIN32
                 connected = true;
                 break;
 #else
@@ -863,10 +858,11 @@ UA_ClientConnectionTCP(UA_ConnectionConfig conf,
         }
         ClientNetworkLayerTCP_close(&connection);
 
-    } while ((UA_Double)(UA_DateTime_nowMonotonic() - connStart)*UA_DATETIME_TO_MSEC < timeout);
+    } while ((UA_DateTime_nowMonotonic() - connStart) < dtTimeout);
 
     freeaddrinfo(server);
-    if (!connected) {
+
+    if(!connected) {
         /* connection timeout */
         ClientNetworkLayerTCP_close(&connection);
         UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,

+ 6 - 8
src/client/ua_client.c

@@ -184,7 +184,7 @@ processServiceResponse(void *application, UA_SecureChannel *channel,
      * TODO: Solve this for client and server together */
     if(rd->client->state >= UA_CLIENTSTATE_SECURECHANNEL &&
        (channel->securityToken.createdAt +
-        (channel->securityToken.revisedLifetime * UA_MSEC_TO_DATETIME))
+        (channel->securityToken.revisedLifetime * UA_DATETIME_MSEC))
        < UA_DateTime_nowMonotonic())
         return UA_STATUSCODE_BADSECURECHANNELCLOSED;
 
@@ -283,11 +283,10 @@ receiveServiceResponse(UA_Client *client, void *response, const UA_DataType *res
             return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
 
         /* round always to upper value to avoid timeout to be set to 0
-         * if (maxDate - now) < (UA_MSEC_TO_DATETIME/2) */
-        UA_UInt32 timeout = (UA_UInt32)(((maxDate - now) + (UA_MSEC_TO_DATETIME - 1)) / UA_MSEC_TO_DATETIME);
+         * if (maxDate - now) < (UA_DATETIME_MSEC/2) */
+        UA_UInt32 timeout = (UA_UInt32)(((maxDate - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
 
-        retval = UA_Connection_receiveChunksBlocking(&client->connection, &rd,
-                                                     client_processChunk, timeout);
+        retval = UA_Connection_receiveChunksBlocking(&client->connection, &rd, client_processChunk, timeout);
 
         if(retval != UA_STATUSCODE_GOOD && retval != UA_STATUSCODE_GOODNONCRITICALTIMEOUT) {
             if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED)
@@ -321,7 +320,7 @@ __UA_Client_Service(UA_Client *client, const void *request,
 
     /* Retrieve the response */
     UA_DateTime maxDate = UA_DateTime_nowMonotonic() +
-        (client->config.timeout * UA_MSEC_TO_DATETIME);
+        (client->config.timeout * UA_DATETIME_MSEC);
     retval = receiveServiceResponse(client, response, responseType, maxDate, &requestId);
     if (retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT){
         /* In synchronous service, if we have don't have a reply we need to close the connection */
@@ -363,8 +362,7 @@ __UA_Client_AsyncService(UA_Client *client, const void *request,
 UA_StatusCode
 UA_Client_runAsync(UA_Client *client, UA_UInt16 timeout) {
     /* TODO: Call repeated jobs that are scheduled */
-    UA_DateTime maxDate = UA_DateTime_nowMonotonic() +
-        (timeout * UA_MSEC_TO_DATETIME);
+    UA_DateTime maxDate = UA_DateTime_nowMonotonic() + (timeout * UA_DATETIME_MSEC);
     UA_StatusCode retval = receiveServiceResponse(client, NULL, NULL, maxDate, NULL);
     if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
         retval = UA_STATUSCODE_GOOD;

+ 2 - 2
src/client/ua_client_connect.c

@@ -127,7 +127,7 @@ processDecodedOPNResponse(UA_Client *client, UA_OpenSecureChannelResponse *respo
      * standard */
     client->channel.state = UA_SECURECHANNELSTATE_OPEN;
     client->nextChannelRenewal = UA_DateTime_nowMonotonic() + (UA_DateTime)
-        (client->channel.securityToken.revisedLifetime * (UA_Double)UA_MSEC_TO_DATETIME * 0.75);
+        (client->channel.securityToken.revisedLifetime * (UA_Double)UA_DATETIME_MSEC * 0.75);
 }
 
 static UA_StatusCode
@@ -178,7 +178,7 @@ openSecureChannel(UA_Client *client, UA_Boolean renew) {
     retval = receiveServiceResponse(client, &response,
                                     &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE],
                                     UA_DateTime_nowMonotonic() +
-                                    ((UA_DateTime)client->config.timeout * UA_MSEC_TO_DATETIME),
+                                    ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC),
                                     &requestId);
                                     
     if(retval != UA_STATUSCODE_GOOD) {

+ 1 - 1
src/client/ua_client_highlevel_subscriptions.c

@@ -406,7 +406,7 @@ UA_Client_Subscriptions_manuallySendPublishRequest(UA_Client *client) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
 
     UA_DateTime now = UA_DateTime_nowMonotonic();
-    UA_DateTime maxDate = now + (UA_DateTime)(client->config.timeout * UA_MSEC_TO_DATETIME);
+    UA_DateTime maxDate = now + (UA_DateTime)(client->config.timeout * UA_DATETIME_MSEC);
 
     UA_Boolean moreNotifications = true;
     while(moreNotifications) {

+ 1 - 1
src/server/ua_securechannel_manager.c

@@ -61,7 +61,7 @@ UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime
     channel_list_entry *entry, *temp;
     LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
         UA_DateTime timeout = entry->channel.securityToken.createdAt +
-            (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_MSEC_TO_DATETIME);
+            (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
         if(timeout < nowMonotonic || !entry->channel.connection) {
             UA_LOG_INFO_CHANNEL(cm->server->config.logger, &entry->channel,
                                 "SecureChannel has timed out");

+ 5 - 6
src/server/ua_server_worker.c

@@ -321,16 +321,16 @@ UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
         UA_Timer_process(&server->timer, now,
                          (UA_TimerDispatchCallback)UA_Server_workerCallback,
                          server);
-    UA_DateTime latest = now + (UA_MAXTIMEOUT * UA_MSEC_TO_DATETIME);
+    UA_DateTime latest = now + (UA_MAXTIMEOUT * UA_DATETIME_MSEC);
     if(nextRepeated > latest)
         nextRepeated = latest;
 
     UA_UInt16 timeout = 0;
 
     /* round always to upper value to avoid timeout to be set to 0
-    * if (nextRepeated - now) < (UA_MSEC_TO_DATETIME/2) */
+    * if (nextRepeated - now) < (UA_DATETIME_MSEC/2) */
     if(waitInternal)
-        timeout = (UA_UInt16)(((nextRepeated - now) + (UA_MSEC_TO_DATETIME - 1)) / UA_MSEC_TO_DATETIME);
+        timeout = (UA_UInt16)(((nextRepeated - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
 
     /* Listen on the networklayer */
     for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
@@ -353,8 +353,7 @@ UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
         // server->mdnsSocket (see example in mdnsd library) on higher level.
         UA_DateTime multicastNextRepeat = 0;
         UA_StatusCode hasNext =
-            iterateMulticastDiscoveryServer(server, &multicastNextRepeat,
-                                            UA_TRUE);
+            iterateMulticastDiscoveryServer(server, &multicastNextRepeat, UA_TRUE);
         if(hasNext == UA_STATUSCODE_GOOD && multicastNextRepeat < nextRepeated)
             nextRepeated = multicastNextRepeat;
     }
@@ -363,7 +362,7 @@ UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
     now = UA_DateTime_nowMonotonic();
     timeout = 0;
     if(nextRepeated > now)
-        timeout = (UA_UInt16)((nextRepeated - now) / UA_MSEC_TO_DATETIME);
+        timeout = (UA_UInt16)((nextRepeated - now) / UA_DATETIME_MSEC);
     return timeout;
 }
 

+ 1 - 1
src/server/ua_services_discovery.c

@@ -521,7 +521,7 @@ void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
     // registration is timed out if lastSeen is older than 60 minutes (default
     // value, can be modified by user).
     if(server->config.discoveryCleanupTimeout)
-        timedOut -= server->config.discoveryCleanupTimeout*UA_SEC_TO_DATETIME;
+        timedOut -= server->config.discoveryCleanupTimeout*UA_DATETIME_SEC;
 
     registeredServer_list_entry* current, *temp;
     LIST_FOREACH_SAFE(current, &server->registeredServers, pointers, temp) {

+ 2 - 2
src/server/ua_services_discovery_multicast.c

@@ -639,8 +639,8 @@ iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
 
     if(nextRepeat)
         *nextRepeat = UA_DateTime_now() +
-            (UA_DateTime)(next_sleep.tv_sec * UA_SEC_TO_DATETIME +
-                          next_sleep.tv_usec * UA_USEC_TO_DATETIME);
+            (UA_DateTime)((next_sleep.tv_sec * UA_DATETIME_SEC) +
+                          (next_sleep.tv_usec * UA_DATETIME_USEC));
     return UA_STATUSCODE_GOOD;
 }
 

+ 3 - 3
src/ua_connection.c

@@ -192,7 +192,7 @@ UA_Connection_receiveChunksBlocking(UA_Connection *connection, void *application
                                     UA_Connection_processChunk processCallback,
                                     UA_UInt32 timeout) {
     UA_DateTime now = UA_DateTime_nowMonotonic();
-    UA_DateTime maxDate = now + (timeout * UA_MSEC_TO_DATETIME);
+    UA_DateTime maxDate = now + (timeout * UA_DATETIME_MSEC);
 
     struct completeChunkTrampolineData data;
     data.called = false;
@@ -223,8 +223,8 @@ UA_Connection_receiveChunksBlocking(UA_Connection *connection, void *application
             return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
 
         /* round always to upper value to avoid timeout to be set to 0
-         * if (maxDate - now) < (UA_MSEC_TO_DATETIME/2) */
-        timeout = (UA_UInt32)(((maxDate - now) + (UA_MSEC_TO_DATETIME - 1)) / UA_MSEC_TO_DATETIME);
+         * if (maxDate - now) < (UA_DATETIME_MSEC/2) */
+        timeout = (UA_UInt32)(((maxDate - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
     }
     return retval;
 }

+ 1 - 1
src/ua_session.c

@@ -95,7 +95,7 @@ void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
 
 void UA_Session_updateLifetime(UA_Session *session) {
     session->validTill = UA_DateTime_nowMonotonic() +
-        (UA_DateTime)(session->timeout * UA_MSEC_TO_DATETIME);
+        (UA_DateTime)(session->timeout * UA_DATETIME_MSEC);
 }
 
 #ifdef UA_ENABLE_SUBSCRIPTIONS

+ 3 - 3
src/ua_timer.c

@@ -102,7 +102,7 @@ UA_Timer_addRepeatedCallback(UA_Timer *t, UA_TimerCallback callback,
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
     /* Set the repeated callback */
-    tc->interval = (UA_UInt64)interval * (UA_UInt64)UA_MSEC_TO_DATETIME;
+    tc->interval = (UA_UInt64)interval * UA_DATETIME_MSEC;
     tc->id = ++t->idCounter;
     tc->callback = callback;
     tc->data = data;
@@ -132,7 +132,7 @@ addTimerCallbackEntry(UA_Timer *t, UA_TimerCallbackEntry * UA_RESTRICT tc) {
          * between "nextTime - 1s" and "nextTime" if this adjustment groups
          * callbacks with the same repetition interval. */
         if(tmpTc->interval == tc->interval &&
-           tmpTc->nextTime > (tc->nextTime - UA_SEC_TO_DATETIME))
+           tmpTc->nextTime > (tc->nextTime - UA_DATETIME_SEC))
             tc->nextTime = tmpTc->nextTime;
     }
 
@@ -157,7 +157,7 @@ UA_Timer_changeRepeatedCallbackInterval(UA_Timer *t, UA_UInt64 callbackId,
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
     /* Set the repeated callback */
-    tc->interval = (UA_UInt64)interval * (UA_UInt64)UA_MSEC_TO_DATETIME;
+    tc->interval = (UA_UInt64)interval * UA_DATETIME_MSEC;
     tc->id = callbackId;
     tc->nextTime = UA_DateTime_nowMonotonic() + (UA_DateTime)tc->interval;
     tc->callback = (UA_TimerCallback)CHANGE_SENTINEL;

+ 1 - 1
src/ua_types.c

@@ -102,7 +102,7 @@ UA_DateTime_toStruct(UA_DateTime t) {
 
     /* Calculating the unix time with #include <time.h> */
     long long secSinceUnixEpoch = (long long)
-        ((t - UA_DATETIME_UNIX_EPOCH) / UA_SEC_TO_DATETIME);
+        ((t - UA_DATETIME_UNIX_EPOCH) / UA_DATETIME_SEC);
     struct mytm ts;
     memset(&ts, 0, sizeof(struct mytm));
     __secs_to_tm(secSinceUnixEpoch, &ts);

+ 0 - 21
tests/check_types_builtin.c

@@ -996,26 +996,6 @@ START_TEST(UA_DateTime_toStructShallWorkOnExample) {
 }
 END_TEST
 
-START_TEST(UA_DateTime_toStringShallWorkOnExample) {
-    // given
-    UA_DateTime src = 13974671891234567 + (11644473600 * 10000000); // ua counts since 1601, unix since 1970
-    //1397467189... is Mon, 14 Apr 2014 09:19:49 GMT
-    //...1234567 are the milli-, micro- and nanoseconds
-
-    UA_String dst;
-
-    // when
-    dst = UA_DateTime_toString(src);
-    // then
-    ck_assert_int_eq(dst.data[0], '0');
-    ck_assert_int_eq(dst.data[1], '4');
-    ck_assert_int_eq(dst.data[2], '/');
-    ck_assert_int_eq(dst.data[3], '1');
-    ck_assert_int_eq(dst.data[4], '4');
-    UA_String_deleteMembers(&dst);
-}
-END_TEST
-
 START_TEST(UA_ExtensionObject_copyShallWorkOnExample) {
     // given
     /* UA_Byte data[3] = { 1, 2, 3 }; */
@@ -1526,7 +1506,6 @@ static Suite *testSuite_builtin(void) {
 
     TCase *tc_convert = tcase_create("convert");
     tcase_add_test(tc_convert, UA_DateTime_toStructShallWorkOnExample);
-    tcase_add_test(tc_convert, UA_DateTime_toStringShallWorkOnExample);
     suite_add_tcase(s, tc_convert);
 
     TCase *tc_copy = tcase_create("copy");

+ 10 - 19
tests/testing-plugins/testing_clock.c

@@ -16,53 +16,44 @@
 #endif
 
 #include <time.h>
-#include "testing_clock.h"
-
 #ifdef _WIN32
-#include <windows.h>	/* WinAPI */
+# include <windows.h>
 #endif
+#include "testing_clock.h"
 
-UA_DateTime testingClock = 0;
 
-UA_DateTime UA_DateTime_diffLocalTimeUTC(void){
-    return 0;
-}
+UA_DateTime testingClock = 0;
 
-UA_DateTime UA_DateTime_nowUtcTime(void) {
+UA_DateTime UA_DateTime_now(void) {
     return testingClock;
 }
 
-UA_DateTime UA_DateTime_nowLocalTime(void) {
+UA_DateTime UA_DateTime_nowMonotonic(void) {
     return testingClock;
 }
 
-UA_DateTime UA_DateTime_nowMonotonic(void) {
-    return testingClock;
+UA_DateTime UA_DateTime_localTimeUtcOffset(void) {
+    return 0;
 }
 
 void
 UA_fakeSleep(UA_UInt32 duration) {
-    testingClock += duration * UA_MSEC_TO_DATETIME;
+    testingClock += duration * UA_DATETIME_MSEC;
 }
 
 /* 1 millisecond = 1,000,000 Nanoseconds */
 #define NANO_SECOND_MULTIPLIER 1000000
 
-#ifdef _WIN32
-
 void
 UA_realSleep(UA_UInt32 duration) {
+#ifdef _WIN32
     Sleep(duration);
-}
-
 #else
-void
-UA_realSleep(UA_UInt32 duration) {
     UA_UInt32 sec = duration / 1000;
     UA_UInt32 ns = (duration % 1000) * NANO_SECOND_MULTIPLIER;
     struct timespec sleepValue;
     sleepValue.tv_sec = sec;
     sleepValue.tv_nsec = ns;
     nanosleep(&sleepValue, NULL);
-}
 #endif
+}

+ 1 - 1
tools/nodeset_compiler/backend_open62541_datatypes.py

@@ -69,7 +69,7 @@ def generateExpandedNodeIdCode(value):
 def generateDateTimeCode(value):
     epoch = datetime.datetime.utcfromtimestamp(0)
     mSecsSinceEpoch = int((value - epoch).total_seconds() * 1000.0)
-    return "( (UA_DateTime)(" + str(mSecsSinceEpoch) + " * UA_MSEC_TO_DATETIME) + UA_DATETIME_UNIX_EPOCH)"
+    return "( (UA_DateTime)(" + str(mSecsSinceEpoch) + " * UA_DATETIME_MSEC) + UA_DATETIME_UNIX_EPOCH)"
 
 def generateNodeValueCode(node, instanceName, asIndirect=False, max_string_length=0):
     if type(node) in [Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float, Double]: