5#ifndef PICOSCENES_PLATFORM_TIMETOOLS_HXX
6#define PICOSCENES_PLATFORM_TIMETOOLS_HXX
13#define DATEFORMAT "%Y-%m-%d %T"
15using namespace std::chrono_literals;
38std::ostream &
operator<<(std::ostream &os,
const std::chrono::system_clock::time_point &t);
46std::ostream &
operator<<(std::ostream &os,
const timespec &ts);
48#if !(defined (_WIN32) || defined(WIN32))
55std::ostream &
operator<<(std::ostream &os,
const timeval &tv);
66 template<
typename TimeUnit = std::chrono::seconds>
68 return std::chrono::time_point_cast<TimeUnit>(std::chrono::seconds(time));
77 template<
typename TimeUnit>
79 auto sec_dur = std::chrono::duration_cast<std::chrono::seconds>(duration);
80 return sec_dur.count();
89 template<
typename TimeUnit = std::chrono::nanoseconds,
typename Rep =
typename TimeUnit::rep,
typename Period =
typename TimeUnit::period>
91 auto duration = std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec};
92 return std::chrono::duration_cast<TimeUnit>(duration);
102 template<
typename Rep,
typename Period>
104 auto sec_dur = std::chrono::duration_cast<std::chrono::seconds>(dur);
105 auto remain_dur = dur - sec_dur;
106 auto remain_nano_dur = std::chrono::duration_cast<std::chrono::nanoseconds>(remain_dur);
108 .tv_sec = sec_dur.count(),
109 .tv_nsec =
static_cast<long>(remain_nano_dur.count()),
113#if !(defined (_WIN32) || defined(WIN32))
120 template<
typename TimeUnit = std::chrono::microseconds>
122 auto duration = std::chrono::seconds{tv.tv_sec} + std::chrono::microseconds{tv.tv_usec};
123 return std::chrono::duration_cast<TimeUnit>(duration);
132 template<
typename TimeUnit>
134 auto sec_dur = std::chrono::duration_cast<std::chrono::seconds>(dur);
135 auto remain_dur = dur - sec_dur;
136 auto remain_micro_dur = std::chrono::duration_cast<std::chrono::microseconds>(remain_dur);
138 .tv_sec = sec_dur.count(),
139 .tv_usec = remain_micro_dur.count(),
150 template<
typename Duration = std::chrono::seconds>
151 std::chrono::time_point<std::chrono::system_clock, Duration>
time_t2TimePoint(
const time_t time) {
152 return std::chrono::time_point_cast<Duration>(std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>(std::chrono::seconds(time)));
161 template<
typename Duration>
162 time_t
time_point2Time_t(
const std::chrono::time_point<std::chrono::system_clock, Duration> &tp) {
163 auto sec_tp = std::chrono::time_point_cast<std::chrono::seconds, std::chrono::system_clock, Duration>(tp);
164 return sec_tp.time_since_epoch().count();
173 template<
typename Duration = std::chrono::nanoseconds>
174 std::chrono::time_point<std::chrono::system_clock, Duration>
timespec2TimePoint(
const timespec &ts) {
175 return std::chrono::time_point<std::chrono::system_clock, Duration>(std::chrono::duration_cast<Duration>(timespec2Duration<Duration>(ts)));
178#if !(defined (_WIN32) || defined(WIN32))
185 template<
typename Duration = std::chrono::microseconds>
186 std::chrono::time_point<std::chrono::system_clock, Duration>
timeval2TimePoint(
const timeval &tv) {
187 return std::chrono::time_point<std::chrono::system_clock, Duration>(std::chrono::duration_cast<Duration>(timeval2Duration<Duration>(tv)));
197 template<
typename Duration>
199 auto sec_tp = std::chrono::time_point_cast<std::chrono::seconds>(tp);
200 auto nano_dur = std::chrono::duration_cast<std::chrono::nanoseconds>(tp - sec_tp);
202 .tv_sec = sec_tp.time_since_epoch().count(),
203 .tv_nsec =
static_cast<long>(nano_dur.count()),
207#if !(defined (_WIN32) || defined(WIN32))
214 template<
typename Duration>
216 auto sec_tp = std::chrono::time_point_cast<std::chrono::seconds>(tp);
217 auto micro_dur = std::chrono::duration_cast<std::chrono::microseconds>(tp - sec_tp);
219 .tv_sec = sec_tp.time_since_epoch().count(),
220 .tv_usec = micro_dur.count(),
230 static timespec time_t2Timespec(
const time_t time) {
242 static time_t timespec2Time_t(
const timespec &ts) {
246#if !(defined (_WIN32) || defined(WIN32))
252 static timeval time_t2timeval(time_t time) {
264 static time_t timeval2Time_t(
const timeval &tv) {
275 static std::string time_t2String(
const time_t time,
const std::string &format =
DATEFORMAT) {
276 std::stringstream ss;
277 ss << std::put_time(std::localtime(&time), format.c_str());
287 static std::string timespec2String(
const timespec &ts,
const std::string &format =
DATEFORMAT) {
288 std::stringstream ss;
289 time_t time = timespec2Time_t(ts);
290 ss << std::put_time(std::localtime(&time), format.c_str());
294#if !(defined (_WIN32) || defined(WIN32))
301 static std::string timeval2String(
const timeval &tv,
const std::string &format =
DATEFORMAT) {
302 std::stringstream ss;
303 time_t time = timeval2Time_t(tv);
304 ss << std::put_time(std::localtime(&time), format.c_str());
316 template<
typename Duration>
318 auto sec_tp = std::chrono::time_point_cast<std::chrono::seconds>(tp);
319 auto timet = std::chrono::system_clock::to_time_t(sec_tp);
320 return time_t2String(timet, format);
330 template<
typename TimeUnit>
333 return time_t2String(time_t, format);
342 static time_t string2time_t(
const std::string &timeString,
const std::string &timeStringFormat =
DATEFORMAT) {
344 #if !(defined (_WIN32) || defined (WIN32))
346 strptime(timeString.c_str(), timeStringFormat.c_str(), &tm);
347 auto time = timelocal(&tm);
353 if (timeStringFormat.find(
"%Z") != std::string::npos || timeStringFormat.find(
"%z") != std::string::npos) {
354 std::string tzformat, timestr;
355 if (timeStringFormat.compare(0, 3,
"%z ") == 0) {
356 tzformat = timeStringFormat.substr(3);
357 timestr = timeString.substr(timeString.find(
' ') + 1);
358 }
else if (timeStringFormat.compare(timeStringFormat.size() - 3, 3,
" %Z") == 0) {
359 tzformat = timeStringFormat.substr(0, timeStringFormat.size() - 3);
360 timestr = timeString.substr(0, timeString.find_last_of(
' '));
362 throw std::runtime_error(timeStringFormat +
" unsupported");
365 std::istringstream ss(timestr);
368 ss >> std::get_time(&tm, tzformat.c_str());
371 throw std::runtime_error(
"Failed to parse time");
377 return _mkgmtime(&tm);
379 std::istringstream ss(timeString);
382 ss >> std::get_time(&tm, timeStringFormat.c_str());
385 throw std::runtime_error(
"Failed to parse time");
402 static struct timespec string2Timespec(const std::string &timeString, const std::string &timeStringFormat =
DATEFORMAT) {
403 return time_t2Timespec(string2time_t(timeString, timeStringFormat));
413 template<
typename Duration = std::chrono::seconds>
414 std::chrono::time_point<std::chrono::system_clock, Duration>
string2time_point(
const std::string &timeString,
const std::string &timeStringFormat =
DATEFORMAT) {
415 auto time_t = string2time_t(timeString, timeStringFormat);
416 return time_t2TimePoint<Duration>(time_t);
426 template<
typename TimeUnit = std::chrono::seconds>
427 static std::chrono::duration<TimeUnit> string2Duration(
const std::string &timeString,
const std::string &timeStringFormat =
DATEFORMAT) {
428 auto time_t = string2time_t(timeString, timeStringFormat);
429 return time_t2Duration<TimeUnit>(time_t);