RTC Toolkit 6.0.0
Loading...
Searching...
No Matches
timeParsing.hpp
Go to the documentation of this file.
1
11
12#ifndef RTCTK_COMPONENTFRAMEWORK_TIME_HPP
13#define RTCTK_COMPONENTFRAMEWORK_TIME_HPP
14
15#include <array>
16#include <chrono>
17#include <format>
18#include <optional>
19#include <spanstream>
20#include <string>
21
23
27// TODO: switch to string_view once https://cplusplus.github.io/LWG/lwg-defects.html#3554 (in C++23)
28// support lands in gcc
29static constexpr std::array<std::string, 5> TIMEPOINT_FORMATS = {
30 "%FT%TZ",
31 "%FT%T%Ez",
32 "%FT%T %Z",
33 "%FT%T",
34 "%FT%R",
35};
54template <class Tp>
55bool ParseTimepoint(const std::string_view time, Tp& timepoint) {
56 // Check if time string contains 'T'
57 if (time.find('T') != std::string::npos) {
58 for (const auto& format : TIMEPOINT_FORMATS) {
59 std::ispanstream time_spanstream(time);
60 time_spanstream >> std::chrono::parse(format, timepoint);
61 if (time_spanstream) {
62 return true;
63 }
64 }
65 }
66 // Check if time string contains ':'
67 else if (time.find(':') != std::string::npos) {
68 auto time_prefixed = std::format("{:%Y-%m-%d}T{}", Tp::clock::now(), time);
69 for (const auto& format : TIMEPOINT_FORMATS) {
70 std::ispanstream time_spanstream(time_prefixed);
71 time_spanstream >> std::chrono::parse(format, timepoint);
72 if (time_spanstream) {
73 return true;
74 }
75 }
76 }
77 // Try just %F format
78 else {
79 std::ispanstream time_spanstream(time);
80 time_spanstream >> std::chrono::parse("%F", timepoint);
81 return static_cast<bool>(time_spanstream);
82 }
83
84 return false;
85}
86
97std::optional<std::chrono::nanoseconds> ParseDuration(const std::string_view duration) {
98 static constexpr std::array<std::pair<std::string_view, std::chrono::nanoseconds>, 39>
99 unit_map = {{// Time units (abbreviations)
100 {"h", std::chrono::hours{1}},
101 {"hr", std::chrono::hours{1}},
102 {"hour", std::chrono::hours{1}},
103 {"hours", std::chrono::hours{1}},
104 {"d", std::chrono::days{1}},
105 {"day", std::chrono::days{1}},
106 {"days", std::chrono::days{1}},
107 {"w", std::chrono::weeks{1}},
108 {"wk", std::chrono::weeks{1}},
109 {"week", std::chrono::weeks{1}},
110 {"weeks", std::chrono::weeks{1}},
111 {"y", std::chrono::years{1}},
112 {"yr", std::chrono::years{1}},
113 {"year", std::chrono::years{1}},
114 {"years", std::chrono::years{1}},
115 {"ms", std::chrono::milliseconds{1}},
116 {"milli", std::chrono::milliseconds{1}},
117 {"millis", std::chrono::milliseconds{1}},
118 {"millisecond", std::chrono::milliseconds{1}},
119 {"milliseconds", std::chrono::milliseconds{1}},
120 {"us", std::chrono::microseconds{1}},
121 {"micro", std::chrono::microseconds{1}},
122 {"micros", std::chrono::microseconds{1}},
123 {"microsecond", std::chrono::microseconds{1}},
124 {"microseconds", std::chrono::microseconds{1}},
125 {"µs", std::chrono::microseconds{1}},
126 {"ns", std::chrono::nanoseconds{1}},
127 {"nano", std::chrono::nanoseconds{1}},
128 {"nanos", std::chrono::nanoseconds{1}},
129 {"nanosecond", std::chrono::nanoseconds{1}},
130 {"nanoseconds", std::chrono::nanoseconds{1}},
131 {"s", std::chrono::seconds{1}},
132 {"sec", std::chrono::seconds{1}},
133 {"second", std::chrono::seconds{1}},
134 {"seconds", std::chrono::seconds{1}},
135 {"m", std::chrono::minutes{1}},
136 {"min", std::chrono::minutes{1}},
137 {"minute", std::chrono::minutes{1}},
138 {"minutes", std::chrono::minutes{1}}}};
139
140 size_t num_end = 0;
141 while (num_end < duration.size() && std::isdigit(duration[num_end])) {
142 ++num_end;
143 }
144
145 if (num_end == 0 or num_end == duration.size()) {
146 return std::nullopt;
147 }
148
149 std::string_view num_str = duration.substr(0, num_end);
150 std::string_view unit_str = duration.substr(num_end);
151
152 while (std::iswspace(unit_str[0])) {
153 unit_str = unit_str.substr(1);
154 if (unit_str.size() == 0) {
155 return std::nullopt;
156 }
157 }
158
159 try {
160 uint64_t value = std::stoul(std::string(num_str));
161 for (const auto& [unit, duration_unit] : unit_map) {
162 if (unit_str.starts_with(unit)) {
163 return std::chrono::nanoseconds(value * duration_unit.count());
164 }
165 }
166 } catch (...) {
167 return std::nullopt;
168 }
169
170 return std::nullopt;
171}
172
173} // namespace rtctk::componentFramework
174
175#endif // RTCTK_COMPONENTFRAMEWORK_TIME_HPP
Definition commandReplier.cpp:21
bool ParseTimepoint(const std::string_view time, Tp &timepoint)
Parses a string representing a timepoint.
Definition timeParsing.hpp:55
std::optional< std::chrono::nanoseconds > ParseDuration(const std::string_view duration)
Parses a string representing a duration.
Definition timeParsing.hpp:97