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