Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_formatting.hpp
Go to the documentation of this file.
1#pragma once
8#ifndef _TIME_SHIELD_TIME_FORMATTING_HPP_INCLUDED
9#define _TIME_SHIELD_TIME_FORMATTING_HPP_INCLUDED
10
11#include "date_time_struct.hpp"
12#include "time_zone_struct.hpp"
13#include "time_conversions.hpp"
14
15namespace time_shield {
16
18 const char& last_char,
19 const size_t& repeat_count,
20 const ts_t& ts,
21 const tz_t& utc_offset,
22 const DateTimeStruct& dt,
23 std::string& result) {
24 switch (last_char) {
25 case 'a':
26 if (repeat_count > 1) break;
27 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::SHORT_NAME);
28 break;
29 case 'A':
30 if (repeat_count > 1) break;
31 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::FULL_NAME);
32 break;
33 case 'I':
34 if (repeat_count == 1) {
35 char buffer[4] = {0};
36 snprintf(buffer, sizeof(buffer), "%.2d", hour24_to_12(dt.hour));
37 result += std::string(buffer);
38 }
39 break;
40 case 'H':
41 if (repeat_count <= 2) {
42 char buffer[4] = {0};
43 snprintf(buffer, sizeof(buffer),"%.2d", dt.hour);
44 result += std::string(buffer);
45 }
46 break;
47 case 'h':
48 if (repeat_count == 2) {
49 char buffer[4] = {0};
50 snprintf(buffer, sizeof(buffer),"%.2d", dt.hour);
51 result += std::string(buffer);
52 break;
53 }
54 // %h: Equivalent to %b
55 case 'b':
56 if (repeat_count > 1) break;
57 result += to_str(static_cast<Month>(dt.mon), FormatType::SHORT_NAME);
58 break;
59 case 'B':
60 if (repeat_count > 1) break;
61 result += to_str(static_cast<Month>(dt.mon), FormatType::FULL_NAME);
62 break;
63 case 'c':
64 // Preferred date and time representation for the current locale.
65 // %a %b %e %H:%M:%S %Y
66 if (repeat_count <= 1){
67 char buffer[16];
68 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::SHORT_NAME);
69 result += " ";
70 result += to_str(static_cast<Month>(dt.mon), FormatType::SHORT_NAME);
71 result += " ";
72 // added %e
73 std::fill(buffer, buffer + sizeof(buffer), '\0');
74 snprintf(buffer, sizeof(buffer),"%2d ", dt.day);
75 result += std::string(buffer);
76 // added %H:%M:%S
77 std::fill(buffer, buffer + sizeof(buffer), '\0');
78 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d ", dt.hour, dt.min, dt.sec);
79 result += std::string(buffer);
80 // added %Y
81 result += std::to_string(dt.year);
82 }
83 break;
84 case 'C':
85 if (repeat_count > 1) break;
86 result += std::to_string(dt.year/100);
87 break;
88 case 'd':
89 if (repeat_count < 2) {
90 char buffer[4] = {0};
91 snprintf(buffer, sizeof(buffer),"%.2d", dt.day);
92 result += std::string(buffer);
93 }
94 break;
95 case 'D':
96 if (repeat_count == 1) {
97 // %m/%d/%y
98 char buffer[16] = {0};
99 snprintf(buffer, sizeof(buffer), "%.2d/%.2d/%.2d", dt.mon, dt.day, (int)(dt.year % 100LL));
100 result += std::string(buffer);
101 } else
102 if (repeat_count == 2) {
103 char buffer[4] = {0};
104 snprintf(buffer, sizeof(buffer),"%.2d", dt.day);
105 result += std::string(buffer);
106 }
107 break;
108 case 'e':
109 if (repeat_count == 1) {
110 char buffer[4] = {0};
111 snprintf(buffer, sizeof(buffer),"%2d", dt.day);
112 result += std::string(buffer);
113 }
114 break;
115 case 'E':
116 // %E: Modifier for alternative ("era-based") format.
117 // https://help.hcltechsw.com/onedb/1.0.0.1/gug/ids_gug_086.html#ids_gug_086
118 break;
119 case 'F':
120 if (repeat_count == 1) {
121 // %Y-%m-%d ISO 8601 date format
122 char buffer[32] = {0};
123 if (dt.year <= 9999 || dt.year >= 0) {
124 snprintf(buffer, sizeof(buffer), "%.4d-%.2d-%.2d", (int)dt.year, dt.mon, dt.day);
125 } else
126 if (dt.year < 0) {
127 snprintf(buffer, sizeof(buffer), "-%lld-%.2d-%.2d", dt.year, dt.mon, dt.day);
128 } else {
129 snprintf(buffer, sizeof(buffer), "+%lld-%.2d-%.2d", dt.year, dt.mon, dt.day);
130 }
131 result += std::string(buffer);
132 }
133 case 'g':
134 // ISO 8601 week-based year without century (2-digit year).
135 break;
136 case 'G':
137 // ISO 8601 week-based year with century as a decimal number.
138 break;
139 case 'j':
140 if (repeat_count == 1) {
141 char buffer[4] = {0};
142 snprintf(buffer, sizeof(buffer), "%.3d", day_of_year(ts));
143 result += std::string(buffer);
144 }
145 break;
146 case 'k':
147 if (repeat_count == 1) {
148 char buffer[4] = {0};
149 snprintf(buffer, sizeof(buffer), "%2d", dt.hour);
150 result += std::string(buffer);
151 }
152 break;
153 case 'l':
154 if (repeat_count == 1) {
155 char buffer[4] = {0};
156 snprintf(buffer, sizeof(buffer), "%2d", hour24_to_12(dt.hour));
157 result += std::string(buffer);
158 }
159 break;
160 case 'm':
161 if (repeat_count == 1) {
162 char buffer[4] = {0};
163 snprintf(buffer, sizeof(buffer), "%.2d", dt.mon);
164 result += std::string(buffer);
165 } else
166 if (repeat_count == 2) {
167 char buffer[4] = {0};
168 snprintf(buffer, sizeof(buffer), "%.2d", dt.min);
169 result += std::string(buffer);
170 }
171 break;
172 case 'M':
173 if (repeat_count == 1) {
174 char buffer[4] = {0};
175 snprintf(buffer, sizeof(buffer), "%.2d", dt.min);
176 result += std::string(buffer);
177 } else
178 if (repeat_count == 2) {
179 char buffer[4] = {0};
180 snprintf(buffer, sizeof(buffer), "%.2d", dt.mon);
181 result += std::string(buffer);
182 } else
183 if (repeat_count == 3) {
184 result += to_str(static_cast<Month>(dt.mon), FormatType::UPPERCASE_NAME);
185 }
186 break;
187 case 'n':
188 result += "\n";
189 break;
190 case 'O':
191 // Modifier for using alternative numeric symbols.
192 break;
193 case 'p':
194 if (dt.hour < 12) result += "AM";
195 else result += "PM";
196 break;
197 case 'P':
198 if (dt.hour < 12) result += "am";
199 else result += "pm";
200 break;
201 case 'r':
202 if (repeat_count == 1) {
203 char buffer[16] = {0};
204 if (dt.hour < 12) snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d AM", hour24_to_12(dt.hour), dt.min, dt.sec);
205 else snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d PM", hour24_to_12(dt.hour), dt.min, dt.sec);
206 result += std::string(buffer);
207 break;
208 }
209 break;
210 case 'R':
211 // %H:%M
212 if (repeat_count == 1) {
213 char buffer[8] = {0};
214 snprintf(buffer, sizeof(buffer), "%.2d:%.2d", dt.hour, dt.min);
215 result += std::string(buffer);
216 }
217 break;
218 case 's':
219 if (repeat_count == 1) {
220 result += std::to_string(ts);
221 break;
222 }
223 if (repeat_count == 4) {
224 result += std::to_string(dt.ms);
225 break;
226 }
227 // to '%ss'
228 case 'S':
229 if (repeat_count <= 2) {
230 char buffer[4] = {0};
231 snprintf(buffer, sizeof(buffer), "%.2d", dt.sec);
232 result += std::string(buffer);
233 }
234 break;
235 case 't':
236 if (repeat_count > 1) break;
237 result += "\t";
238 break;
239 case 'T':
240 // %H:%M:%S
241 if (repeat_count == 1) {
242 char buffer[16] = {0};
243 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d", dt.hour, dt.min, dt.sec);
244 result += std::string(buffer);
245 }
246 break;
247 case 'u':
248 if (repeat_count == 1) {
249 // Day of the week as a decimal number (1 to 7, Monday being 1).
250 int dw = day_of_week(dt.year, dt.mon, dt.day);
251 if (dw == 0) dw = 7;
252 result += std::to_string(dw);
253 }
254 break;
255 case 'U':
256 // Week number of the current year (00 to 53, starting with the first Sunday as week 01).
257 break;
258 case 'V':
259 // ISO 8601 week number of the current year (01 to 53, with specific rules).
260 break;
261 case 'w':
262 // Day of the week as a decimal number (0 to 6, Sunday being 0).
263 if (repeat_count == 1) {
264 result += std::to_string(day_of_week(dt.year, dt.mon, dt.day));
265 } else
266 if (repeat_count == 3) {
267 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::SHORT_NAME);
268 }
269 break;
270 case 'W':
271 // Week number of the current year (00 to 53, starting with the first Monday as week 01).
272 if (repeat_count == 3) {
274 }
275 break;
276 case 'x':
277 // Preferred date representation for the current locale without the time.
278 break;
279 case 'X':
280 // Preferred time representation for the current locale without the date.
281 break;
282 case 'y':
283 if (repeat_count == 1) {
284 result += std::to_string(dt.year % 100);
285 }
286 break;
287 case 'Y':
288 if (repeat_count == 1) {
289 result += std::to_string(dt.year);
290 } else
291 if (repeat_count == 6) {
292 char buffer[32] = {0};
293 const int64_t mega_years = dt.year / 1000000;
294 const int64_t millennia = (dt.year - mega_years * 1000000) / 1000;
295 const int64_t centuries = dt.year - mega_years * 1000000 - millennia * 1000;
296 if (mega_years) {
297 if (millennia) {
298 snprintf(buffer, sizeof(buffer), "%lldM%lldK%.3lld", mega_years, std::abs(millennia), std::abs(centuries));
299 } else {
300 snprintf(buffer, sizeof(buffer), "%lldM%.3lld", mega_years, std::abs(centuries));
301 }
302 } else
303 if (millennia) {
304 snprintf(buffer, sizeof(buffer), "%lldK%.3lld", millennia, std::abs(centuries));
305 } else {
306 snprintf(buffer, sizeof(buffer), "%.4lld", dt.year);
307 }
308 result += std::string(buffer);
309 } else
310 if (repeat_count == 4) {
311 char buffer[8] = {0};
312 snprintf(buffer, sizeof(buffer), "%.4d", (int)(dt.year % 10000));
313 result += std::string(buffer);
314 } else
315 if (repeat_count == 2) {
316 char buffer[8] = {0};
317 snprintf(buffer, sizeof(buffer), "%.2d", (int)(dt.year % 100));
318 result += std::string(buffer);
319 }
320 break;
321 case 'z':
322 // +hhmm or -hhmm numeric timezone offset from UTC.
323 if (repeat_count == 1) {
324 TimeZoneStruct tz = to_time_zone_struct(utc_offset);
325 char buffer[16] = {0};
326 if (tz.is_positive) snprintf(buffer, sizeof(buffer), "+%.2d%.2d", tz.hour, tz.min);
327 else snprintf(buffer, sizeof(buffer), "-%.2d%.2d", tz.hour, tz.min);
328 result += std::string(buffer);
329 }
330 break;
331 case 'Z':
332 // Timezone name or abbreviation.
333
334 result += "UTC";
335 break;
336 case '+':
337 // Date and time in date(1) format (not supported in glibc2).
338 // Tue Jun 4 04:07:43 UTC 2024
339 break;
340 };
341 }
342
369 template<class T = ts_t>
370 const std::string to_string(
371 const std::string& format_str,
372 const T& timestamp,
373 const tz_t& utc_offset = 0) {
374 std::string result;
375 if (format_str.empty()) return result;
377
378 char buffer[32];
379
380 bool is_command = false;
381 size_t repeat_count = 0;
382 char last_char = format_str[0];
383 if (last_char != '%') result += last_char;
384 for (size_t i = 0; i < format_str.size(); ++i) {
385 const char& current_char = format_str[i];
386 if (!is_command) {
387 if (current_char == '%') {
388 ++repeat_count;
389 if (repeat_count == 2) {
390 result += current_char;
391 repeat_count = 0;
392 }
393 continue;
394 }
395 if (!repeat_count) {
396 result += current_char;
397 continue;
398 }
399 last_char = current_char;
400 is_command = true;
401 continue;
402 }
403 if (last_char == current_char) {
404 ++repeat_count;
405 continue;
406 }
407 process_format_impl(last_char, repeat_count, timestamp, utc_offset, dt, result);
408 repeat_count = 0;
409 is_command = false;
410 --i;
411 }
412 if (is_command) {
413 process_format_impl(last_char, repeat_count, timestamp, utc_offset, dt, result);
414 }
415 return result;
416 }
417
420 template<class T = ts_t>
421 inline const std::string to_str(
422 const std::string& format_str,
423 const T& timestamp,
424 const tz_t& utc_offset = 0) {
425 return to_string<T>(format_str, timestamp, utc_offset);
426 }
427
435 template<class T = ts_t>
436 inline const std::string to_iso8601_str(const T& ts) {
438 char buffer[32] = {0};
439 if TIME_SHIELD_CONSTEXPR (std::is_floating_point<T>::value) {
440 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms);
441 } else {
442 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec);
443 }
444 return std::string(buffer);
445 }
446
454 template<class T = ts_t>
455 inline const std::string to_iso8601_date_str(const T& ts) {
457 char buffer[32] = {0};
458 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2d", dt.year, dt.mon, dt.day);
459 return std::string(buffer);
460 }
461
469 template<class T = ts_t>
470 inline const std::string to_iso8601_time_str(const T& ts) {
472 char buffer[32] = {0};
473 if TIME_SHIELD_CONSTEXPR (std::is_floating_point<T>::value) {
474 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d.%.3d", dt.hour, dt.min, dt.sec, dt.ms);
475 } else {
476 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d", dt.hour, dt.min, dt.sec);
477 }
478 return std::string(buffer);
479 }
480
488 template<class T = ts_t>
489 inline const std::string to_iso8601_time_utc_str(const T& ts) {
491 char buffer[32] = {0};
492 if TIME_SHIELD_CONSTEXPR (std::is_floating_point<T>::value) {
493 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d.%.3dZ", dt.hour, dt.min, dt.sec, dt.ms);
494 } else {
495 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2dZ", dt.hour, dt.min, dt.sec);
496 }
497 return std::string(buffer);
498 }
499
507 template<class T = ts_t>
508 inline const std::string to_iso8601_utc_str(const T& ts) {
510 char buffer[32] = {0};
511 if TIME_SHIELD_CONSTEXPR (std::is_floating_point<T>::value) {
512 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms);
513 } else {
514 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2dZ", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec);
515 }
516 return std::string(buffer);
517 }
518
525 inline const std::string to_iso8601_utc_str_ms(const ts_ms_t& ts_ms) {
527 char buffer[32] = {0};
528 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms);
529 return std::string(buffer);
530 }
531
538 inline const std::string to_iso8601_str_ms(const ts_ms_t& ts_ms) {
540 char buffer[32] = {0};
541 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms);
542 return std::string(buffer);
543 }
544
553 template<class T = ts_t>
554 inline const std::string to_iso8601_str(const T& ts, const tz_t &utc_offset) {
555 TimeZoneStruct tz = to_time_zone(utc_offset);
557 char buffer[32] = {0};
558 if TIME_SHIELD_CONSTEXPR (std::is_floating_point<T>::value) {
559 if (tz.is_positive) {
560 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d+%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms, tz.hour, tz.min);
561 } else {
562 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d-%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms, tz.hour, tz.min);
563 }
564 } else {
565 if (tz.is_positive) {
566 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d+%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, tz.hour, tz.min);
567 } else {
568 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d-%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, tz.hour, tz.min);
569 }
570 }
571 return std::string(buffer);
572 }
573
581 inline const std::string to_iso8601_str_ms(const ts_ms_t& ts_ms, const tz_t &utc_offset) {
582 TimeZoneStruct tz = to_time_zone(utc_offset);
584 char buffer[32] = {0};
585 if (tz.is_positive) {
586 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d+%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms, tz.hour, tz.min);
587 } else {
588 snprintf(buffer, sizeof(buffer), "%lld-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d-%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec, dt.ms, tz.hour, tz.min);
589 }
590 return std::string(buffer);
591 }
592
599 inline const std::string to_mql5_date_time_str(const ts_t& ts) {
601 char buffer[32] = {0};
602 snprintf(buffer, sizeof(buffer), "%lld.%.2d.%.2d %.2d:%.2d:%.2d", dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec);
603 return std::string(buffer);
604 }
605
608 inline const std::string to_mql5_full_str(const ts_t& ts) {
610 }
611
618 inline const std::string to_mql5_date_str(const ts_t& ts) {
620 char buffer[32] = {0};
621 snprintf(buffer, sizeof(buffer), "%lld.%.2d.%.2d", dt.year, dt.mon, dt.day);
622 return std::string(buffer);
623 }
624
631 inline const std::string to_mql5_time_str(const ts_t& ts) {
633 char buffer[32] = {0};
634 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d", dt.hour, dt.min, dt.sec);
635 return std::string(buffer);
636 }
637
638}; // namespace time_shield
639
640#endif // _TIME_SHIELD_TIME_FORMATTING_HPP_INCLUDED
#define TIME_SHIELD_CONSTEXPR
Definition config.hpp:16
Header for date and time structure and related functions.
Main namespace for the Time Shield library.
Definition constants.hpp:12
const std::string & to_str(const Weekday &value, const FormatType &format=UPPERCASE_NAME)
Converts a Weekday enum value to a string.
Definition enums.hpp:63
int64_t ts_t
Integer timestamp type.
Definition types.hpp:15
const std::string to_iso8601_time_str(const T &ts)
Converts a timestamp to an ISO8601 time string.
const std::string to_mql5_time_str(const ts_t &ts)
Converts a timestamp to a string in MQL5 time format.
const std::string to_string(const std::string &format_str, const T &timestamp, const tz_t &utc_offset=0)
Convert timestamp to string with custom format.
TIME_SHIELD_CONSTEXPR const T hour24_to_12(const T &hour) noexcept
Converts a 24-hour format hour to a 12-hour format.
int64_t ts_ms_t
Integer timestamp milliseconds type.
Definition types.hpp:16
const TimeZoneStruct to_time_zone_struct(const tz_t &offset)
Converts an integer to a TimeZoneStruct.
const std::string to_iso8601_utc_str(const T &ts)
Converts a timestamp to an ISO8601 string in UTC format.
const TimeZoneStruct to_time_zone(const tz_t &offset)
Converts an integer to a time zone structure.
const std::string to_mql5_date_time_str(const ts_t &ts)
Converts a timestamp to a string in MQL5 date and time format.
const std::string to_iso8601_utc_str_ms(const ts_ms_t &ts_ms)
Converts a timestamp in milliseconds to an ISO8601 string in UTC format.
const ts_t timestamp() noexcept
Get the current UTC timestamp in seconds.
const ts_ms_t ts_ms() noexcept
Get the current UTC timestamp in milliseconds.
const T day_of_year(const ts_t &ts=ts())
Get the day of the year.
void process_format_impl(const char &last_char, const size_t &repeat_count, const ts_t &ts, const tz_t &utc_offset, const DateTimeStruct &dt, std::string &result)
const std::string to_mql5_full_str(const ts_t &ts)
Alias for to_mql5_date_time_str function.
constexpr const T1 day_of_week(const T2 &year, const T3 &month, const T3 &day)
Alias for day_of_week_date function.
@ SHORT_NAME
Short name.
Definition enums.hpp:17
@ UPPERCASE_NAME
Uppercase short name.
Definition enums.hpp:16
@ FULL_NAME
Full name.
Definition enums.hpp:18
T to_date_time_ms(const ts_ms_t &ts)
Converts a timestamp in milliseconds to a date-time structure with milliseconds.
const std::string to_iso8601_time_utc_str(const T &ts)
Converts a timestamp to an ISO8601 UTC time string.
T1 to_date_time(const T2 &ts)
Converts a timestamp to a date-time structure.
const std::string to_mql5_date_str(const ts_t &ts)
Converts a timestamp to a string in MQL5 date format.
Month
Enumeration of the months of the year.
Definition enums.hpp:85
const std::string to_iso8601_str(const T &ts)
Converts a timestamp to an ISO8601 string.
const ts_t ts() noexcept
Get the current UTC timestamp in seconds.
const std::string to_iso8601_str_ms(const ts_ms_t &ts_ms)
Converts a timestamp in milliseconds to an ISO8601 string.
const std::string to_iso8601_date_str(const T &ts)
Converts a timestamp to an ISO8601 date string.
Structure to represent date and time.
int ms
Millisecond component of time (0-999)
int hour
Hour component of time (0-23)
int64_t year
Year component of the date.
int day
Day component of the date (1-31).
int min
Minute component of time (0-59)
int mon
Month component of the date (1-12).
int sec
Second component of time (0-59)
Structure to represent time zone information.
int hour
Hour component of time (0-23)
int min
Minute component of time (0-59)
bool is_positive
True if the time zone offset is positive, false if negative.
Header file for time conversion functions.
Header for time zone structure and related functions.