master
c 81 lines 2.98 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "../libnetdata.h"
4
5 size_t iso8601_datetime_ut(char *buffer, size_t len, usec_t now_ut, ISO8601_OPTIONS options) {
6 if(unlikely(!buffer || len == 0))
7 return 0;
8
9 time_t t = (time_t)(now_ut / USEC_PER_SEC);
10 struct tm *tmp, tmbuf;
11
12 if(options & ISO8601_UTC)
13 // Use gmtime_r for UTC time conversion.
14 tmp = gmtime_r(&t, &tmbuf);
15 else
16 // Use localtime_r for local time conversion.
17 tmp = localtime_r(&t, &tmbuf);
18
19 if (unlikely(!tmp)) {
20 buffer[0] = '\0';
21 return 0;
22 }
23
24 // Format the date and time according to the ISO 8601 format.
25 size_t used_length = strftime(buffer, len, "%Y-%m-%dT%H:%M:%S", tmp);
26 if (unlikely(used_length == 0)) {
27 buffer[0] = '\0';
28 return 0;
29 }
30
31 if(options & ISO8601_MILLISECONDS) {
32 // Calculate the remaining microseconds
33 int milliseconds = (int) ((now_ut % USEC_PER_SEC) / USEC_PER_MS);
34 if(milliseconds && len - used_length > 4)
35 used_length += snprintfz(buffer + used_length, len - used_length, ".%03d", milliseconds);
36 }
37 else if(options & ISO8601_MICROSECONDS) {
38 // Calculate the remaining microseconds
39 int microseconds = (int) (now_ut % USEC_PER_SEC);
40 if(microseconds && len - used_length > 7)
41 used_length += snprintfz(buffer + used_length, len - used_length, ".%06d", microseconds);
42 }
43
44 if(options & ISO8601_UTC) {
45 if(used_length + 1 < len) {
46 buffer[used_length++] = 'Z';
47 buffer[used_length] = '\0'; // null-terminate the string.
48 }
49 }
50 else {
51 // Calculate the timezone offset in hours and minutes from UTC.
52 long offset = tmbuf.tm_gmtoff;
53 int hours = (int) (offset / 3600); // Convert offset seconds to hours.
54 int minutes = (int) ((offset % 3600) / 60); // Convert remainder to minutes (keep the sign for minutes).
55
56 // Check if timezone is UTC.
57 if(hours == 0 && minutes == 0) {
58 // For UTC, append 'Z' to the timestamp.
59 if(used_length + 1 < len) {
60 buffer[used_length++] = 'Z';
61 buffer[used_length] = '\0'; // null-terminate the string.
62 }
63 }
64 else {
65 // For non-UTC, format the timezone offset. Omit minutes if they are zero.
66 if(minutes == 0) {
67 // Check enough space is available for the timezone offset string.
68 if(used_length + 3 < len) // "+hh\0"
69 used_length += snprintfz(buffer + used_length, len - used_length, "%+03d", hours);
70 }
71 else {
72 // Check enough space is available for the timezone offset string.
73 if(used_length + 6 < len) // "+hh:mm\0"
74 used_length += snprintfz(buffer + used_length, len - used_length,
75 "%+03d:%02d", hours, abs(minutes));
76 }
77 }
78 }
79
80 return used_length;
81 }