Branch data Line data Source code
1 : : #include "rational.h"
2 : :
3 : : #include <stdio.h>
4 : :
5 : : // Time functions (gettimeofday)
6 : : #include <sys/time.h>
7 : :
8 : : /**
9 : : * @brief Current time in milliseconds
10 : : * @return Returns long long int the number of milliseconds since the UNIX epoch
11 : : */
12 : 3 : long long int cur_time_ms(void)
13 : : {
14 : : struct timeval t;
15 : 3 : gettimeofday(&t,NULL);
16 : 3 : long long mt = (long long)t.tv_sec * 1000 + t.tv_usec / 1000;
17 : 3 : return(mt);
18 : : }
19 : :
20 : : /**
21 : : * @brief Current time in nanoseconds
22 : : * @return long long int number of nanoseconds, count starts at the Unix Epoch on January 1st, 1970 at UTC
23 : : * @details Source: https://stackoverflow.com/questions/39439268/printing-time-since-epoch-in-nanoseconds
24 : : */
25 : 1034 : long long int cur_time_ns(void)
26 : : {
27 : : long long int ns;
28 : : time_t sec;
29 : : struct timespec spec;
30 : 1034 : clock_gettime(CLOCK_REALTIME,&spec);
31 : 1034 : sec = spec.tv_sec;
32 : 1034 : ns = spec.tv_nsec;
33 : 1034 : return(((long long int)sec * 1000000000LL) + ns);
34 : : }
35 : :
36 : : /**
37 : : * @brief Current monotonic time in nanoseconds
38 : : * @return long long int number of nanoseconds from a monotonic clock source
39 : : * @details Counter starts at an unspecified point and is intended for interval measurement.
40 : : * Unlike CLOCK_REALTIME, this source is not affected by wall-clock adjustments.
41 : : */
42 : : #if defined(CLOCK_MONOTONIC) && (!defined(_POSIX_MONOTONIC_CLOCK) || (_POSIX_MONOTONIC_CLOCK >= 0))
43 : 8435 : long long int cur_time_monotonic_ns(void)
44 : : {
45 : : long long int ns;
46 : : time_t sec;
47 : : struct timespec spec;
48 : 8435 : clock_gettime(CLOCK_MONOTONIC,&spec);
49 : 8435 : sec = spec.tv_sec;
50 : 8435 : ns = spec.tv_nsec;
51 : 8435 : return(((long long int)sec * 1000000000LL) + ns);
52 : : }
53 : : #endif
54 : :
55 : : /**
56 : : * @brief Convert a UNIX time in seconds to a local-time ISO-like timestamp
57 : : *
58 : : * @details The input is interpreted as seconds since the Unix epoch and
59 : : * converted to local time through localtime_r(). The returned text has the
60 : : * fixed shape "YYYY-MM-DD HH:MM:SS" and is written into a function-local
61 : : * static buffer, so consecutive calls reuse the same storage and overwrite
62 : : * the previous result. To obtain the current time, pass the result of
63 : : * `time(NULL)` rather than zero; zero refers to the Unix epoch itself
64 : : *
65 : : * @param seconds Seconds since the Unix epoch to format
66 : : * @return Pointer to a static buffer with the formatted text
67 : : */
68 : 322 : char *seconds_to_ISOdate(time_t seconds)
69 : : {
70 : : // String to store converted time
71 : : static char str_t[sizeof "2011-10-18 07:07:09"] = "";
72 : 322 : str_t[0] = '\0'; /* Initialize buffer as empty string */
73 : :
74 : : // Pointer to a structure with local time
75 : : struct tm cur_time;
76 : :
77 : : // Convert system time to local time
78 : 322 : localtime_r(&seconds,&cur_time);
79 : :
80 : : // Create a string with date and time accurate to seconds
81 : 322 : strftime(str_t,sizeof(str_t),"%Y-%m-%d %H:%M:%S",&cur_time);
82 : :
83 : : #if 0
84 : : printf("current time: %s \n",str_t);
85 : : #endif
86 : :
87 : 322 : return(str_t);
88 : : }
89 : :
90 : : /**
91 : : *
92 : : * @brief "As a date", Convert nanoseconds to date format
93 : : *
94 : : */
95 : : __attribute__((always_inline)) static inline Date asadate(const long long int nanoseconds)
96 : : {
97 : : /// Number of nanoseconds in a year
98 : : /// 365*24*60*60*1000*1000*1000
99 : 1011 : const long long int ns_in_year = 31536000000000000LL;
100 : :
101 : : /// Number of nanoseconds in a month
102 : : /// ns_in_year/12
103 : 1011 : const long long int ns_in_month = 2628000000000000LL;
104 : :
105 : : /// Number of nanoseconds in a week
106 : : /// 7*24*60*60*1000*1000*1000
107 : 1011 : const long long int ns_in_week = 604800000000000LL;
108 : :
109 : : /// Number of nanoseconds in a day
110 : : /// 24*60*60*1000*1000*1000
111 : 1011 : const long long int ns_in_day = 86400000000000LL;
112 : :
113 : : /// Number of nanoseconds in an hour
114 : : /// 60*60*1000*1000*1000
115 : 1011 : const long long int ns_in_hour = 3600000000000LL;
116 : :
117 : : /// Number of nanoseconds in a minute
118 : : /// 60*1000*1000*1000
119 : 1011 : const long long int ns_in_minute = 60000000000LL;
120 : :
121 : : /// Number of nanoseconds in a second
122 : : /// 1000*1000*1000
123 : 1011 : const long long int ns_in_second = 1000000000LL;
124 : :
125 : : /// Number of nanoseconds in a millisecond
126 : : /// 1000*1000
127 : 1011 : const long long int ns_in_millisecond = 1000000LL;
128 : :
129 : : /// Number of nanoseconds in a microsecond
130 : : /// 1000
131 : 1011 : const long long int ns_in_microsecond = 1000LL;
132 : :
133 : : // Initializing the structure that will be returned from the function
134 : 1011 : Date date = {0};
135 : :
136 : 1011 : date.years = nanoseconds/ns_in_year;
137 : :
138 : 1011 : const long long int years_ns = date.years * ns_in_year;
139 : 1011 : date.months = (nanoseconds - years_ns)/ns_in_month;
140 : :
141 : 1011 : const long long int months_ns = date.months * ns_in_month;
142 : 1011 : date.weeks = (nanoseconds - years_ns - months_ns)/ns_in_week;
143 : :
144 : 1011 : const long long int weeks_ns = date.weeks * ns_in_week;
145 : 1011 : date.days = (nanoseconds - years_ns - months_ns - weeks_ns)/ns_in_day;
146 : :
147 : 1011 : const long long int days_ns = date.days * ns_in_day;
148 : 1011 : date.hours = (nanoseconds - years_ns - months_ns - weeks_ns - days_ns)/ns_in_hour;
149 : :
150 : 1011 : const long long int hours_ns = date.hours * ns_in_hour;
151 : 1011 : date.minutes = (nanoseconds - years_ns - months_ns - weeks_ns - days_ns - hours_ns)/ns_in_minute;
152 : :
153 : 1011 : const long long int minutes_ns = date.minutes * ns_in_minute;
154 : 1011 : date.seconds = (nanoseconds - years_ns - months_ns - weeks_ns - days_ns - hours_ns - minutes_ns)/ns_in_second;
155 : :
156 : 1011 : const long long int seconds_ns = date.seconds * ns_in_second;
157 : 1011 : date.milliseconds = (nanoseconds - years_ns - months_ns - weeks_ns - days_ns - hours_ns - minutes_ns - seconds_ns)/ns_in_millisecond;
158 : :
159 : 1011 : const long long int milliseconds_ns = date.milliseconds * ns_in_millisecond;
160 : 1011 : date.microseconds = (nanoseconds - years_ns - months_ns - weeks_ns - days_ns - hours_ns - minutes_ns - seconds_ns - milliseconds_ns)/ns_in_microsecond;
161 : :
162 : 1011 : const long long int microseconds_ns = date.microseconds * ns_in_microsecond;
163 : 1011 : date.nanoseconds = (nanoseconds - years_ns - months_ns - weeks_ns - days_ns - hours_ns - minutes_ns - seconds_ns - milliseconds_ns - microseconds_ns);
164 : :
165 : 1011 : return(date);
166 : : }
167 : :
168 : : /**
169 : : *
170 : : * The function for convert nanoseconds to a readable date. The function
171 : : * generates a string if the structure element contains time data greater
172 : : * than zero.
173 : : *
174 : : */
175 : 5277 : static void catdate_r(
176 : : char *const result,
177 : : const size_t result_size,
178 : : size_t *const used_len,
179 : : const long long int number,
180 : : const char *const suffix)
181 : : {
182 [ + + - + ]: 5277 : if(number <= 0LL || *used_len >= result_size)
183 : : {
184 : 3514 : return;
185 : : }
186 : :
187 : 1763 : const int written = snprintf(result + *used_len,result_size - *used_len,"%lld%s ",number,suffix);
188 : :
189 [ + + ]: 1763 : if(written < 0)
190 : : {
191 : 1 : return;
192 : : }
193 : :
194 : 1762 : const size_t write_size = (size_t)written;
195 : :
196 [ + + ]: 1762 : if(write_size >= result_size - *used_len)
197 : : {
198 : 5 : *used_len = result_size - 1ULL;
199 : 5 : result[result_size - 1ULL] = '\0';
200 : : } else {
201 : 1757 : *used_len += write_size;
202 : : }
203 : : }
204 : :
205 : : /**
206 : : *
207 : : * Convert nanoseconds to human-readable date as a string
208 : : *
209 : : */
210 : 1065 : char *form_date_r(
211 : : const long long int nanoseconds,
212 : : const ByteFormat format,
213 : : char *buffer,
214 : : const size_t buffer_size)
215 : : {
216 [ + + + + ]: 1065 : if(buffer == NULL || buffer_size == 0ULL)
217 : : {
218 : 2 : return(NULL);
219 : : }
220 : :
221 : 1063 : buffer[0] = '\0'; /* Initialize buffer as empty string */
222 : 1063 : size_t used_len = 0ULL;
223 : :
224 : : // If the time passed as argument is less than one nanosecond
225 [ + + ]: 1063 : if(nanoseconds == 0LL)
226 : : {
227 : 52 : (void)snprintf(buffer,buffer_size,"0ns");
228 : 52 : return(buffer);
229 : : }
230 : :
231 : : Date date = asadate(nanoseconds);
232 : :
233 [ + + ]: 1011 : if(format == MAJOR_VIEW)
234 : : {
235 [ + + ]: 537 : if(date.years > 0LL)
236 : : {
237 : 2 : catdate_r(buffer,buffer_size,&used_len,date.years,"y");
238 [ + + ]: 535 : } else if(date.months > 0LL){
239 : 2 : catdate_r(buffer,buffer_size,&used_len,date.months,"mon");
240 [ + + ]: 533 : } else if(date.weeks > 0LL){
241 : 2 : catdate_r(buffer,buffer_size,&used_len,date.weeks,"w");
242 [ + + ]: 531 : } else if(date.days > 0LL){
243 : 2 : catdate_r(buffer,buffer_size,&used_len,date.days,"d");
244 [ + + ]: 529 : } else if(date.hours > 0LL){
245 : 3 : catdate_r(buffer,buffer_size,&used_len,date.hours,"h");
246 [ + + ]: 526 : } else if(date.minutes > 0LL){
247 : 2 : catdate_r(buffer,buffer_size,&used_len,date.minutes,"min");
248 [ + + ]: 524 : } else if(date.seconds > 0LL){
249 : 14 : catdate_r(buffer,buffer_size,&used_len,date.seconds,"s");
250 [ + + ]: 510 : } else if(date.milliseconds > 0LL){
251 : 254 : catdate_r(buffer,buffer_size,&used_len,date.milliseconds,"ms");
252 [ + + ]: 256 : } else if(date.microseconds > 0LL){
253 : 242 : catdate_r(buffer,buffer_size,&used_len,date.microseconds,"μs");
254 : : } else {
255 : 14 : catdate_r(buffer,buffer_size,&used_len,date.nanoseconds,"ns");
256 : : }
257 : : } else {
258 : 474 : catdate_r(buffer,buffer_size,&used_len,date.years,"y");
259 : 474 : catdate_r(buffer,buffer_size,&used_len,date.months,"mon");
260 : 474 : catdate_r(buffer,buffer_size,&used_len,date.weeks,"w");
261 : 474 : catdate_r(buffer,buffer_size,&used_len,date.days,"d");
262 : 474 : catdate_r(buffer,buffer_size,&used_len,date.hours,"h");
263 : 474 : catdate_r(buffer,buffer_size,&used_len,date.minutes,"min");
264 : 474 : catdate_r(buffer,buffer_size,&used_len,date.seconds,"s");
265 : 474 : catdate_r(buffer,buffer_size,&used_len,date.milliseconds,"ms");
266 : 474 : catdate_r(buffer,buffer_size,&used_len,date.microseconds,"μs");
267 : 474 : catdate_r(buffer,buffer_size,&used_len,date.nanoseconds,"ns");
268 : : }
269 : :
270 : : // Remove trailing space at the end of the line.
271 [ + + + + ]: 1011 : if(used_len > 0ULL && buffer[used_len - 1ULL] == ' ')
272 : : {
273 : 1006 : buffer[used_len - 1ULL] = '\0';
274 : : }
275 : :
276 : 1011 : return(buffer);
277 : : }
278 : :
279 : : /**
280 : : *
281 : : * Convert nanoseconds to human-readable date as a string
282 : : *
283 : : */
284 : 533 : char *form_date(
285 : : const long long int nanoseconds,
286 : : const ByteFormat format)
287 : : {
288 : : // Zero out a static memory area with a string array
289 : : static char result[MAX_CHARACTERS];
290 : :
291 : 533 : return(form_date_r(nanoseconds,format,result,sizeof(result)));
292 : : }
293 : : #if 0
294 : : /// Test
295 : :
296 : : /// To build
297 : : /// gcc -I../../logger/lib/ time.c
298 : :
299 : : /// 339800645368118513 = ((365*24*60*60*1000*1000*1000)*10) + (((365*24*60*60*1000*1000*1000)/12)*9)+((7*24*60*60*1000*1000*1000)*1)+((24*60*60*1000*1000*1000)*2)+((60*60*1000*1000*1000)*3)+((60*1000*1000*1000)*4)+((1000*1000*1000)*5)+((1000*1000)*368)+((1000)*118)+513
300 : : /// Should be 10y 9mon 1w 2d 3h 4min 5s 368ms 118μs 513ns
301 : :
302 : : int main(void)
303 : : {
304 : : long long int ns = 339800645368118513LL;
305 : : printf("%s\n",form_date(ns,FULL_VIEW));
306 : :
307 : : printf("%s\n",form_date(273522528,FULL_VIEW));
308 : :
309 : : return 0;
310 : : }
311 : : #endif
|