Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_formatting.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2#pragma once
3#ifndef _TIME_SHIELD_TIME_FORMATTING_HPP_INCLUDED
4#define _TIME_SHIELD_TIME_FORMATTING_HPP_INCLUDED
5
12
13#include "config.hpp"
14#include "date_time_struct.hpp"
16#include "time_zone_struct.hpp"
17#include "time_conversions.hpp"
18
19#include <inttypes.h>
20
21namespace time_shield {
22
25
27 char last_char,
28 size_t repeat_count,
29 ts_t ts,
30 tz_t utc_offset,
31 const DateTimeStruct& dt,
32 std::string& result) {
33 switch (last_char) {
34 case 'a':
35 if (repeat_count > 1) break;
36 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::SHORT_NAME);
37 break;
38 case 'A':
39 if (repeat_count > 1) break;
40 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::FULL_NAME);
41 break;
42 case 'I':
43 if (repeat_count == 1) {
44 char buffer[4] = {0};
45 snprintf(buffer, sizeof(buffer), "%.2d", hour24_to_12(dt.hour));
46 result += std::string(buffer);
47 }
48 break;
49 case 'H':
50 if (repeat_count <= 2) {
51 char buffer[4] = {0};
52 snprintf(buffer, sizeof(buffer),"%.2d", dt.hour);
53 result += std::string(buffer);
54 }
55 break;
56 case 'h':
57 if (repeat_count == 2) {
58 char buffer[4] = {0};
59 snprintf(buffer, sizeof(buffer),"%.2d", dt.hour);
60 result += std::string(buffer);
61 break;
62 }
63
64 // fallthrough
65 case 'b':
66 // %h: Equivalent to %b
67 if (repeat_count > 1) break;
68 result += to_str(static_cast<Month>(dt.mon), FormatType::SHORT_NAME);
69 break;
70 case 'B':
71 if (repeat_count > 1) break;
72 result += to_str(static_cast<Month>(dt.mon), FormatType::FULL_NAME);
73 break;
74 case 'c':
75 // Preferred date and time representation for the current locale.
76 // %a %b %e %H:%M:%S %Y
77 if (repeat_count <= 1){
78 char buffer[16];
79 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::SHORT_NAME);
80 result += " ";
81 result += to_str(static_cast<Month>(dt.mon), FormatType::SHORT_NAME);
82 result += " ";
83 // added %e
84 std::fill(buffer, buffer + sizeof(buffer), '\0');
85 snprintf(buffer, sizeof(buffer),"%2d ", dt.day);
86 result += std::string(buffer);
87 // added %H:%M:%S
88 std::fill(buffer, buffer + sizeof(buffer), '\0');
89 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d ", dt.hour, dt.min, dt.sec);
90 result += std::string(buffer);
91 // added %Y
92 result += std::to_string(dt.year);
93 }
94 break;
95 case 'C':
96 if (repeat_count > 1) break;
97 result += std::to_string(dt.year/100);
98 break;
99 case 'd':
100 if (repeat_count < 2) {
101 char buffer[4] = {0};
102 snprintf(buffer, sizeof(buffer),"%.2d", dt.day);
103 result += std::string(buffer);
104 }
105 break;
106 case 'D':
107 if (repeat_count == 1) {
108 // %m/%d/%y
109 char buffer[16] = {0};
110 snprintf(buffer, sizeof(buffer), "%.2d/%.2d/%.2d", dt.mon, dt.day, (int)(dt.year % 100LL));
111 result += std::string(buffer);
112 } else
113 if (repeat_count == 2) {
114 char buffer[4] = {0};
115 snprintf(buffer, sizeof(buffer),"%.2d", dt.day);
116 result += std::string(buffer);
117 }
118 break;
119 case 'e':
120 if (repeat_count == 1) {
121 char buffer[4] = {0};
122 snprintf(buffer, sizeof(buffer),"%2d", dt.day);
123 result += std::string(buffer);
124 }
125 break;
126 case 'E':
127 // %E: Modifier for alternative ("era-based") format.
128 // https://help.hcltechsw.com/onedb/1.0.0.1/gug/ids_gug_086.html#ids_gug_086
129 break;
130 case 'F':
131 if (repeat_count == 1) {
132 // %Y-%m-%d ISO 8601 date format
133 char buffer[32] = {0};
134 if (dt.year <= 9999 && dt.year >= 0) {
135 snprintf(buffer, sizeof(buffer), "%.4d-%.2d-%.2d", (int)dt.year, dt.mon, dt.day);
136 } else
137 if (dt.year < 0) {
138 snprintf(buffer, sizeof(buffer), "-%" PRId64 "-%.2d-%.2d", dt.year, dt.mon, dt.day);
139 } else {
140 snprintf(buffer, sizeof(buffer), "+%" PRId64 "-%.2d-%.2d", dt.year, dt.mon, dt.day);
141 }
142 result += std::string(buffer);
143 }
144 break;
145 case 'g':
146 // ISO 8601 week-based year without century (2-digit year).
147 if (repeat_count == 1) {
148 const IsoWeekDateStruct iso_week = to_iso_week_date(dt.year, dt.mon, dt.day);
149 const int two_digit_year = static_cast<int>(iso_week.year % 100);
150 char buffer[4] = {0};
151 snprintf(buffer, sizeof(buffer), "%.2d", two_digit_year < 0 ? -two_digit_year : two_digit_year);
152 result += std::string(buffer);
153 }
154 break;
155 case 'G':
156 // ISO 8601 week-based year with century as a decimal number.
157 if (repeat_count == 1) {
158 const IsoWeekDateStruct iso_week = to_iso_week_date(dt.year, dt.mon, dt.day);
159 result += std::to_string(iso_week.year);
160 }
161 break;
162 case 'j':
163 if (repeat_count == 1) {
164 char buffer[4] = {0};
165 snprintf(buffer, sizeof(buffer), "%.3d", day_of_year(ts));
166 result += std::string(buffer);
167 }
168 break;
169 case 'k':
170 if (repeat_count == 1) {
171 char buffer[4] = {0};
172 snprintf(buffer, sizeof(buffer), "%2d", dt.hour);
173 result += std::string(buffer);
174 }
175 break;
176 case 'l':
177 if (repeat_count == 1) {
178 char buffer[4] = {0};
179 snprintf(buffer, sizeof(buffer), "%2d", hour24_to_12(dt.hour));
180 result += std::string(buffer);
181 }
182 break;
183 case 'm':
184 if (repeat_count == 1) {
185 char buffer[4] = {0};
186 snprintf(buffer, sizeof(buffer), "%.2d", dt.mon);
187 result += std::string(buffer);
188 } else
189 if (repeat_count == 2) {
190 char buffer[4] = {0};
191 snprintf(buffer, sizeof(buffer), "%.2d", dt.min);
192 result += std::string(buffer);
193 }
194 break;
195 case 'M':
196 if (repeat_count == 1) {
197 char buffer[4] = {0};
198 snprintf(buffer, sizeof(buffer), "%.2d", dt.min);
199 result += std::string(buffer);
200 } else
201 if (repeat_count == 2) {
202 char buffer[4] = {0};
203 snprintf(buffer, sizeof(buffer), "%.2d", dt.mon);
204 result += std::string(buffer);
205 } else
206 if (repeat_count == 3) {
207 result += to_str(static_cast<Month>(dt.mon), FormatType::UPPERCASE_NAME);
208 }
209 break;
210 case 'n':
211 result += "\n";
212 break;
213 case 'O':
214 // Modifier for using alternative numeric symbols.
215 break;
216 case 'p':
217 if (dt.hour < 12) result += "AM";
218 else result += "PM";
219 break;
220 case 'P':
221 if (dt.hour < 12) result += "am";
222 else result += "pm";
223 break;
224 case 'r':
225 if (repeat_count == 1) {
226 char buffer[16] = {0};
227 if (dt.hour < 12) snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d AM", hour24_to_12(dt.hour), dt.min, dt.sec);
228 else snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d PM", hour24_to_12(dt.hour), dt.min, dt.sec);
229 result += std::string(buffer);
230 break;
231 }
232 break;
233 case 'R':
234 // %H:%M
235 if (repeat_count == 1) {
236 char buffer[8] = {0};
237 snprintf(buffer, sizeof(buffer), "%.2d:%.2d", dt.hour, dt.min);
238 result += std::string(buffer);
239 }
240 break;
241 case 's':
242 if (repeat_count == 1) {
243 result += std::to_string(ts);
244 break;
245 }
246 if (repeat_count == 3) {
247 result += std::to_string(dt.ms);
248 break;
249 }
250 // to '%ss'
251
252 // fallthrough
253 case 'S':
254 if (repeat_count <= 2) {
255 char buffer[4] = {0};
256 snprintf(buffer, sizeof(buffer), "%.2d", dt.sec);
257 result += std::string(buffer);
258 }
259 if (repeat_count == 3) {
260 result += std::to_string(dt.ms);
261 break;
262 }
263 break;
264 case 't':
265 if (repeat_count > 1) break;
266 result += "\t";
267 break;
268 case 'T':
269 // %H:%M:%S
270 if (repeat_count == 1) {
271 char buffer[16] = {0};
272 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d", dt.hour, dt.min, dt.sec);
273 result += std::string(buffer);
274 }
275 break;
276 case 'u':
277 if (repeat_count == 1) {
278 // Day of the week as a decimal number (1 to 7, Monday being 1).
279 int dw = day_of_week(dt.year, dt.mon, dt.day);
280 if (dw == 0) dw = 7;
281 result += std::to_string(dw);
282 }
283 break;
284 case 'U':
285 // Week number of the current year (00 to 53, starting with the first Sunday as week 01).
286 break;
287 case 'V':
288 // ISO 8601 week number of the current year (01 to 53, with specific rules).
289 if (repeat_count == 1) {
290 const IsoWeekDateStruct iso_week = to_iso_week_date(dt.year, dt.mon, dt.day);
291 char buffer[4] = {0};
292 snprintf(buffer, sizeof(buffer), "%.2d", iso_week.week);
293 result += std::string(buffer);
294 }
295 break;
296 case 'w':
297 // Day of the week as a decimal number (0 to 6, Sunday being 0).
298 if (repeat_count == 1) {
299 result += std::to_string(day_of_week(dt.year, dt.mon, dt.day));
300 } else
301 if (repeat_count == 3) {
302 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::SHORT_NAME);
303 }
304 break;
305 case 'W':
306 // Week number of the current year (00 to 53, starting with the first Monday as week 01).
307 if (repeat_count == 3) {
308 result += to_str(day_of_week(dt.year, dt.mon, dt.day), FormatType::UPPERCASE_NAME);
309 }
310 break;
311 case 'x':
312 // Preferred date representation for the current locale without the time.
313 break;
314 case 'X':
315 // Preferred time representation for the current locale without the date.
316 break;
317 case 'y':
318 if (repeat_count == 1) {
319 result += std::to_string(dt.year % 100);
320 }
321 break;
322 case 'Y':
323 if (repeat_count == 1) {
324 result += std::to_string(dt.year);
325 } else
326 if (repeat_count == 6) {
327 char buffer[32] = {0};
328 const int64_t mega_years = dt.year / 1000000;
329 const int64_t millennia = (dt.year - mega_years * 1000000) / 1000;
330 const int64_t centuries = dt.year - mega_years * 1000000 - millennia * 1000;
331 if (mega_years) {
332 if (millennia) {
333 snprintf(
334 buffer,
335 sizeof(buffer),
336 "%" PRId64 "M%" PRId64 "K%.3" PRId64,
337 mega_years,
338 static_cast<int64_t>(std::abs(millennia)),
339 static_cast<int64_t>(std::abs(centuries)));
340 } else {
341 snprintf(
342 buffer,
343 sizeof(buffer),
344 "%" PRId64 "M%.3" PRId64,
345 mega_years,
346 static_cast<int64_t>(std::abs(centuries)));
347 }
348 } else
349 if (millennia) {
350 snprintf(
351 buffer,
352 sizeof(buffer),
353 "%" PRId64 "K%.3" PRId64,
354 millennia,
355 static_cast<int64_t>(std::abs(centuries)));
356 } else {
357 snprintf(buffer, sizeof(buffer), "%.4" PRId64, dt.year);
358 }
359 result += std::string(buffer);
360 } else
361 if (repeat_count == 4) {
362 char buffer[8] = {0};
363 snprintf(buffer, sizeof(buffer), "%.4d", (int)(dt.year % 10000));
364 result += std::string(buffer);
365 } else
366 if (repeat_count == 2) {
367 char buffer[8] = {0};
368 snprintf(buffer, sizeof(buffer), "%.2d", (int)(dt.year % 100));
369 result += std::string(buffer);
370 }
371 break;
372 case 'z':
373 // +hhmm or -hhmm numeric timezone offset from UTC.
374 if (repeat_count == 1) {
375 TimeZoneStruct tz = to_time_zone_struct(utc_offset);
376 char buffer[16] = {0};
377 if (tz.is_positive) snprintf(buffer, sizeof(buffer), "+%.2d%.2d", tz.hour, tz.min);
378 else snprintf(buffer, sizeof(buffer), "-%.2d%.2d", tz.hour, tz.min);
379 result += std::string(buffer);
380 }
381 break;
382 case 'Z':
383 // Timezone name or abbreviation.
384
385 result += "UTC";
386 break;
387 case '+':
388 // Date and time in date(1) format (not supported in glibc2).
389 // Tue Jun 4 04:07:43 UTC 2024
390 break;
391 };
392 }
393
424 template<class T = ts_t>
425 const std::string to_string(
426 const std::string& format_str,
427 T timestamp,
428 tz_t utc_offset = 0) {
429 std::string result;
430 if (format_str.empty()) return result;
431 const T local_timestamp = static_cast<T>(timestamp + static_cast<T>(utc_offset));
432 DateTimeStruct dt = to_date_time<DateTimeStruct>(local_timestamp);
433
434 bool is_command = false;
435 size_t repeat_count = 0;
436 char last_char = format_str[0];
437 if (last_char != '%') result += last_char;
438 for (size_t i = 0; i < format_str.size(); ++i) {
439 const char& current_char = format_str[i];
440 if (!is_command) {
441 if (current_char == '%') {
442 ++repeat_count;
443 if (repeat_count == 2) {
444 result += current_char;
445 repeat_count = 0;
446 }
447 continue;
448 }
449 if (!repeat_count) {
450 result += current_char;
451 continue;
452 }
453 last_char = current_char;
454 is_command = true;
455 continue;
456 }
457 if (last_char == current_char) {
458 ++repeat_count;
459 continue;
460 }
461 process_format_impl(last_char, repeat_count, timestamp, utc_offset, dt, result);
462 repeat_count = 0;
463 is_command = false;
464 --i;
465 }
466 if (is_command) {
467 process_format_impl(last_char, repeat_count, timestamp, utc_offset, dt, result);
468 }
469 return result;
470 }
471
474 template<class T = ts_t>
475 inline const std::string to_str(
476 const std::string& format_str,
477 T timestamp,
478 tz_t utc_offset = 0) {
479 return to_string<T>(format_str, timestamp, utc_offset);
480 }
481
508 template<class T = ts_ms_t>
509 const std::string to_string_ms(
510 const std::string& format_str,
511 T timestamp,
512 tz_t utc_offset = 0) {
513 std::string result;
514 if (format_str.empty()) return result;
515 const T local_timestamp = static_cast<T>(timestamp + sec_to_ms<T, tz_t>(utc_offset));
517
518 bool is_command = false;
519 size_t repeat_count = 0;
520 char last_char = format_str[0];
521 if (last_char != '%') result += last_char;
522 for (size_t i = 0; i < format_str.size(); ++i) {
523 const char& current_char = format_str[i];
524 if (!is_command) {
525 if (current_char == '%') {
526 ++repeat_count;
527 if (repeat_count == 2) {
528 result += current_char;
529 repeat_count = 0;
530 }
531 continue;
532 }
533 if (!repeat_count) {
534 result += current_char;
535 continue;
536 }
537 last_char = current_char;
538 is_command = true;
539 continue;
540 }
541 if (last_char == current_char) {
542 ++repeat_count;
543 continue;
544 }
545 process_format_impl(last_char, repeat_count, timestamp, utc_offset, dt, result);
546 repeat_count = 0;
547 is_command = false;
548 --i;
549 }
550 if (is_command) {
551 process_format_impl(last_char, repeat_count, timestamp, utc_offset, dt, result);
552 }
553 return result;
554 }
555
558 template<class T = ts_t>
559 inline const std::string to_str_ms(
560 const std::string& format_str,
561 T timestamp,
562 tz_t utc_offset = 0) {
563 return to_string_ms<T>(format_str, timestamp, utc_offset);
564 }
565
573 template<class T = ts_t>
574 inline const std::string to_iso8601(T ts) {
576 char buffer[32] = {0};
577 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T>::value) {
578 snprintf(
579 buffer,
580 sizeof(buffer),
581 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d",
582 dt.year,
583 dt.mon,
584 dt.day,
585 dt.hour,
586 dt.min,
587 dt.sec,
588 dt.ms);
589 } else {
590 snprintf(
591 buffer,
592 sizeof(buffer),
593 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d",
594 dt.year,
595 dt.mon,
596 dt.day,
597 dt.hour,
598 dt.min,
599 dt.sec);
600 }
601 return std::string(buffer);
602 }
603
611 template<class T = ts_t>
612 inline const std::string to_iso8601_date(T ts) {
614 char buffer[32] = {0};
615 snprintf(
616 buffer,
617 sizeof(buffer),
618 "%" PRId64 "-%.2d-%.2d",
619 dt.year,
620 dt.mon,
621 dt.day);
622 return std::string(buffer);
623 }
624
632 template<class T = ts_t>
633 inline const std::string to_iso8601_time(T ts) {
635 char buffer[32] = {0};
636 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T>::value) {
637 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d.%.3d", dt.hour, dt.min, dt.sec, dt.ms);
638 } else {
639 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d", dt.hour, dt.min, dt.sec);
640 }
641 return std::string(buffer);
642 }
643
651 template<class T = ts_t>
652 inline const std::string to_iso8601_time_utc(T ts) {
654 char buffer[32] = {0};
655 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T>::value) {
656 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d.%.3dZ", dt.hour, dt.min, dt.sec, dt.ms);
657 } else {
658 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2dZ", dt.hour, dt.min, dt.sec);
659 }
660 return std::string(buffer);
661 }
662
670 template<class T = ts_t>
671 inline const std::string to_iso8601_utc(T ts) {
673 char buffer[32] = {0};
674 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T>::value) {
675 snprintf(
676 buffer,
677 sizeof(buffer),
678 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
679 dt.year,
680 dt.mon,
681 dt.day,
682 dt.hour,
683 dt.min,
684 dt.sec,
685 dt.ms);
686 } else {
687 snprintf(
688 buffer,
689 sizeof(buffer),
690 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2dZ",
691 dt.year,
692 dt.mon,
693 dt.day,
694 dt.hour,
695 dt.min,
696 dt.sec);
697 }
698 return std::string(buffer);
699 }
700
707 inline const std::string to_iso8601_utc_ms(ts_ms_t ts_ms) {
709 char buffer[32] = {0};
710 snprintf(
711 buffer,
712 sizeof(buffer),
713 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
714 dt.year,
715 dt.mon,
716 dt.day,
717 dt.hour,
718 dt.min,
719 dt.sec,
720 dt.ms);
721 return std::string(buffer);
722 }
723
730 inline const std::string to_iso8601_ms(ts_ms_t ts_ms) {
732 char buffer[32] = {0};
733 snprintf(
734 buffer,
735 sizeof(buffer),
736 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d",
737 dt.year,
738 dt.mon,
739 dt.day,
740 dt.hour,
741 dt.min,
742 dt.sec,
743 dt.ms);
744 return std::string(buffer);
745 }
746
755 template<class T = ts_t>
756 inline const std::string to_iso8601(T ts, tz_t utc_offset) {
757 TimeZoneStruct tz = to_time_zone(utc_offset);
758 const T local_ts = static_cast<T>(ts + static_cast<T>(utc_offset));
759 DateTimeStruct dt = to_date_time(local_ts);
760 char buffer[32] = {0};
761 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T>::value) {
762 if (tz.is_positive) {
763 snprintf(
764 buffer,
765 sizeof(buffer),
766 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d+%.2d:%.2d",
767 dt.year,
768 dt.mon,
769 dt.day,
770 dt.hour,
771 dt.min,
772 dt.sec,
773 dt.ms,
774 tz.hour,
775 tz.min);
776 } else {
777 snprintf(
778 buffer,
779 sizeof(buffer),
780 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d-%.2d:%.2d",
781 dt.year,
782 dt.mon,
783 dt.day,
784 dt.hour,
785 dt.min,
786 dt.sec,
787 dt.ms,
788 tz.hour,
789 tz.min);
790 }
791 } else {
792 if (tz.is_positive) {
793 snprintf(
794 buffer,
795 sizeof(buffer),
796 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d+%.2d:%.2d",
797 dt.year,
798 dt.mon,
799 dt.day,
800 dt.hour,
801 dt.min,
802 dt.sec,
803 tz.hour,
804 tz.min);
805 } else {
806 snprintf(
807 buffer,
808 sizeof(buffer),
809 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d-%.2d:%.2d",
810 dt.year,
811 dt.mon,
812 dt.day,
813 dt.hour,
814 dt.min,
815 dt.sec,
816 tz.hour,
817 tz.min);
818 }
819 }
820 return std::string(buffer);
821 }
822
830 inline const std::string to_iso8601_ms(ts_ms_t ts_ms, tz_t utc_offset) {
831 TimeZoneStruct tz = to_time_zone(utc_offset);
832 const ts_ms_t local_ts_ms = ts_ms + sec_to_ms<ts_ms_t, tz_t>(utc_offset);
834 char buffer[32] = {0};
835 if (tz.is_positive) {
836 snprintf(
837 buffer,
838 sizeof(buffer),
839 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d+%.2d:%.2d",
840 dt.year,
841 dt.mon,
842 dt.day,
843 dt.hour,
844 dt.min,
845 dt.sec,
846 dt.ms,
847 tz.hour,
848 tz.min);
849 } else {
850 snprintf(
851 buffer,
852 sizeof(buffer),
853 "%" PRId64 "-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d-%.2d:%.2d",
854 dt.year,
855 dt.mon,
856 dt.day,
857 dt.hour,
858 dt.min,
859 dt.sec,
860 dt.ms,
861 tz.hour,
862 tz.min);
863 }
864 return std::string(buffer);
865 }
866
873 inline const std::string to_mql5_date_time(ts_t ts) {
875 char buffer[32] = {0};
876 snprintf(
877 buffer,
878 sizeof(buffer),
879 "%" PRId64 ".%.2d.%.2d %.2d:%.2d:%.2d",
880 dt.year,
881 dt.mon,
882 dt.day,
883 dt.hour,
884 dt.min,
885 dt.sec);
886 return std::string(buffer);
887 }
888
891 inline const std::string to_mql5_full(ts_t ts) {
892 return to_mql5_date_time(ts);
893 }
894
901 inline const std::string to_mql5_date(ts_t ts) {
903 char buffer[32] = {0};
904 snprintf(
905 buffer,
906 sizeof(buffer),
907 "%" PRId64 ".%.2d.%.2d",
908 dt.year,
909 dt.mon,
910 dt.day);
911 return std::string(buffer);
912 }
913
920 inline const std::string to_mql5_time(ts_t ts) {
922 char buffer[32] = {0};
923 snprintf(buffer, sizeof(buffer), "%.2d:%.2d:%.2d", dt.hour, dt.min, dt.sec);
924 return std::string(buffer);
925 }
926
930 inline const std::string to_windows_filename(ts_t ts) {
932 char buffer[32] = {0};
933 snprintf(
934 buffer,
935 sizeof(buffer),
936 "%" PRId64 "-%.2d-%.2d_%.2d-%.2d-%.2d",
937 dt.year,
938 dt.mon,
939 dt.day,
940 dt.hour,
941 dt.min,
942 dt.sec);
943 return std::string(buffer);
944 }
945
949 inline const std::string to_windows_filename_ms(ts_ms_t ts) {
951 char buffer[32] = {0};
952 snprintf(
953 buffer,
954 sizeof(buffer),
955 "%" PRId64 "-%.2d-%.2d_%.2d-%.2d-%.2d-%.3d",
956 dt.year,
957 dt.mon,
958 dt.day,
959 dt.hour,
960 dt.min,
961 dt.sec,
962 dt.ms);
963 return std::string(buffer);
964 }
965
969 inline std::string to_human_readable(ts_t ts) {
971 char buffer[32] = {0};
972 snprintf(
973 buffer,
974 sizeof(buffer),
975 "%" PRId64 "-%.2d-%.2d %.2d:%.2d:%.2d",
976 dt.year,
977 dt.mon,
978 dt.day,
979 dt.hour,
980 dt.min,
981 dt.sec);
982 return std::string(buffer);
983 }
984
988 inline std::string to_human_readable_ms(ts_ms_t ts) {
990 char buffer[32] = {0};
991 snprintf(
992 buffer,
993 sizeof(buffer),
994 "%" PRId64 "-%.2d-%.2d %.2d:%.2d:%.2d.%.3d",
995 dt.year,
996 dt.mon,
997 dt.day,
998 dt.hour,
999 dt.min,
1000 dt.sec,
1001 dt.ms);
1002 return std::string(buffer);
1003 }
1004
1006
1007}; // namespace time_shield
1008
1009#endif // _TIME_SHIELD_TIME_FORMATTING_HPP_INCLUDED
Configuration macros for the library.
Header for date and time structure and related functions.
TIME_SHIELD_CONSTEXPR ts_t timestamp(year_t year, int month, int day)
Alias for to_timestamp.
TIME_SHIELD_CONSTEXPR ts_t ts(year_t year, int month, int day)
Alias for to_timestamp.
IsoWeekDateStruct to_iso_week_date(Y year, M month, D day)
Convert calendar date to ISO week date.
TIME_SHIELD_CONSTEXPR T hour24_to_12(T hour) noexcept
Converts a 24-hour format hour to a 12-hour format.
T to_time_zone(tz_t offset)
Converts an integer to a time zone structure.
TIME_SHIELD_CONSTEXPR ts_ms_t ts_ms(year_t year, int month, int day)
Alias for to_timestamp_ms.
TIME_SHIELD_CONSTEXPR T1 day_of_week(year_t year, int month, int day)
Alias for day_of_week_date.
TIME_SHIELD_CONSTEXPR T1 sec_to_ms(T2 ts) noexcept
Converts a timestamp from seconds to milliseconds.
const std::string & to_str(Weekday value, FormatType format=UPPERCASE_NAME)
Converts a Weekday enum value to a string.
Definition enums.hpp:70
const std::string to_string(const std::string &format_str, T timestamp, tz_t utc_offset=0)
Convert timestamp to string with custom format.
const std::string to_iso8601_ms(ts_ms_t ts_ms)
Converts a timestamp in milliseconds to an ISO8601 string.
const std::string to_mql5_date_time(ts_t ts)
Converts a timestamp to a string in MQL5 date and time format.
const std::string to_iso8601_time(T ts)
Converts a timestamp to an ISO8601 time string.
void process_format_impl(char last_char, size_t repeat_count, ts_t ts, tz_t utc_offset, const DateTimeStruct &dt, std::string &result)
const std::string to_windows_filename(ts_t ts)
Converts a timestamp in seconds to a Windows-compatible filename format.
const std::string to_iso8601_date(T ts)
Converts a timestamp to an ISO8601 date string.
const std::string to_mql5_date(ts_t ts)
Converts a timestamp to a string in MQL5 date format.
const std::string to_mql5_full(ts_t ts)
Alias for to_mql5_date_time_str function.
const std::string to_mql5_time(ts_t ts)
Converts a timestamp to a string in MQL5 time format.
const std::string to_str_ms(const std::string &format_str, T timestamp, tz_t utc_offset=0)
Alias for to_string function.
std::string to_human_readable(ts_t ts)
Converts a timestamp in seconds to a human-readable format.
const std::string to_iso8601_utc_ms(ts_ms_t ts_ms)
Converts a timestamp in milliseconds to an ISO8601 string in UTC format.
const std::string to_iso8601(T ts)
Converts a timestamp to an ISO8601 string.
std::string to_human_readable_ms(ts_ms_t ts)
Converts a timestamp in milliseconds to a human-readable format.
const std::string to_iso8601_time_utc(T ts)
Converts a timestamp to an ISO8601 UTC time string.
const std::string to_string_ms(const std::string &format_str, T timestamp, tz_t utc_offset=0)
Convert timestamp in milliseconds to string with custom format.
const std::string to_windows_filename_ms(ts_ms_t ts)
Converts a timestamp in milliseconds to a Windows-compatible filename format.
const std::string to_iso8601_utc(T ts)
Converts a timestamp to an ISO8601 string in UTC format.
TimeZoneStruct to_time_zone_struct(tz_t offset)
Converts an integer to a TimeZoneStruct.
T to_date_time_ms(ts_ms_t ts)
Converts a timestamp in milliseconds to a date-time structure with milliseconds.
T day_of_year(ts_t ts=time_shield::ts())
Get the day of the year.
T1 to_date_time(T2 ts)
Converts a timestamp to a date-time structure.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:49
int32_t tz_t
Time zone offset in minutes from UTC (e.g., +180 = UTC+3).
Definition types.hpp:61
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:50
Conversions and utilities for ISO week dates (ISO 8601).
Main namespace for the Time Shield library.
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 an ISO week date.
int64_t year
ISO week-numbering year component.
int32_t week
ISO week number component (1-52/53).
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.
Umbrella header for time conversion functions.
Header for time zone structure and related functions.