refactor: + indentlog/timeutil/, for clarity
This commit is contained in:
parent
38101cce90
commit
eaa5f3ada3
4 changed files with 304 additions and 289 deletions
|
|
@ -37,7 +37,7 @@ namespace xo {
|
|||
std::ostream & ss() { return ss_; }
|
||||
|
||||
void check_print_time(utc_nanos now_tm) {
|
||||
using xo::time::time;
|
||||
using xo::time::timeutil;
|
||||
using xo::time::utc_nanos;
|
||||
using xo::time::hms_msec;
|
||||
using xo::time::hms_usec;
|
||||
|
|
@ -190,7 +190,7 @@ namespace xo {
|
|||
|
||||
sbuf->reset_stream();
|
||||
|
||||
this->check_print_time(xo::time::time::now());
|
||||
this->check_print_time(xo::time::timeutil::now());
|
||||
this->indent(' ');
|
||||
|
||||
char ee_label = '\0';
|
||||
|
|
|
|||
|
|
@ -2,284 +2,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#ifdef NOT_YET
|
||||
# include <format>
|
||||
#endif
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <time.h>
|
||||
#include "indentlog/timeutil/timeutil.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace time {
|
||||
|
||||
using utc_nanos = std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::nanoseconds>;
|
||||
|
||||
using nanos = std::chrono::nanoseconds;
|
||||
using microseconds = std::chrono::microseconds;
|
||||
using milliseconds = std::chrono::milliseconds;
|
||||
using seconds = std::chrono::seconds;
|
||||
using hours = std::chrono::hours;
|
||||
using days = std::chrono::days;
|
||||
|
||||
struct time {
|
||||
static utc_nanos now() {
|
||||
return utc_nanos(std::chrono::system_clock::now());
|
||||
}
|
||||
|
||||
static utc_nanos epoch() {
|
||||
return utc_nanos(std::chrono::system_clock::from_time_t(0));
|
||||
} /*epoch*/
|
||||
|
||||
static utc_nanos ymd_hms(uint32_t ymd, uint32_t hms) {
|
||||
/* e.g. ymd=20220610 -> n_yr=2022, n_mon=06, n_dy=10 */
|
||||
|
||||
uint32_t n_yr = ymd / 10000;
|
||||
uint32_t n_mon = (ymd % 10000) / 100;
|
||||
uint32_t n_dy = ymd % 100;
|
||||
|
||||
uint32_t n_hr = hms / 10000;
|
||||
uint32_t n_min = (hms % 10000) / 100;
|
||||
uint32_t n_sec = hms % 100;
|
||||
|
||||
struct tm t;
|
||||
|
||||
t.tm_year = n_yr - 1900; /* 0 means 1900 */
|
||||
t.tm_mon = n_mon - 1; /* 0 means january */
|
||||
t.tm_mday = n_dy;
|
||||
|
||||
t.tm_hour = n_hr; /* 24 hour clock */
|
||||
t.tm_min = n_min;
|
||||
t.tm_sec = n_sec;
|
||||
|
||||
/* time since epoch */
|
||||
time_t epoch_time = timegm(&t);
|
||||
|
||||
return std::chrono::system_clock::from_time_t(epoch_time);
|
||||
} /*ymd_hms*/
|
||||
|
||||
/* midnight UTC on date ymd.
|
||||
* e.g. ymd_midnight(20220707) -> midnight UTC on 7jul22
|
||||
*/
|
||||
static utc_nanos ymd_midnight(uint32_t ymd) {
|
||||
return ymd_hms(ymd, 0);
|
||||
} /*ymd_midnight*/
|
||||
|
||||
static utc_nanos ymd_hms_usec(uint32_t ymd, uint32_t hms, uint32_t usec) {
|
||||
utc_nanos s = ymd_hms(ymd, hms);
|
||||
|
||||
return s + microseconds(usec);
|
||||
} /*ymd_hms_usec*/
|
||||
|
||||
/* .first: UTC midnight on same calendar day as t0
|
||||
* .second: elapsed time from .first to t0 (i.e. UTC time-of-day for t0)
|
||||
*/
|
||||
static std::pair<utc_nanos, nanos> utc_split_vs_midnight(utc_nanos t0) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
time_t t0_time_t = (std::chrono::system_clock::to_time_t
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(t0)));
|
||||
|
||||
/* convert to std::tm,
|
||||
* only provides 1-second precision
|
||||
*/
|
||||
std::tm t0_tm;
|
||||
::gmtime_r(&t0_time_t, &t0_tm);
|
||||
|
||||
/* midnight on the same calendar day as t0_tm */
|
||||
std::tm midnight_tm = t0_tm;
|
||||
{
|
||||
midnight_tm.tm_hour = 0;
|
||||
midnight_tm.tm_min = 0;
|
||||
midnight_tm.tm_sec = 0;
|
||||
}
|
||||
|
||||
/* convert to UTC epoch seconds */
|
||||
time_t midnight_time_t = ::timegm(&midnight_tm);
|
||||
|
||||
utc_nanos t0_midnight =
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(
|
||||
std::chrono::system_clock::from_time_t(midnight_time_t)));
|
||||
|
||||
nanos t0_tdy = t0 - t0_midnight;
|
||||
|
||||
return std::pair<utc_nanos, nanos>(t0_midnight, t0_tdy);
|
||||
} /*utc_split_vs_midnight*/
|
||||
|
||||
/* .first: LOCAL midnight on same calendar day as t0 (but in UTC coords)
|
||||
* .second: elapsed time from .first to t0 (i.e. LOCAL time-of-day for t0)
|
||||
*/
|
||||
static std::pair<utc_nanos, nanos> local_split_vs_midnight(utc_nanos t0) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
time_t t0_time_t = (std::chrono::system_clock::to_time_t
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(t0)));
|
||||
|
||||
/* convert to std::tm,
|
||||
* only provides 1-second precision
|
||||
*/
|
||||
std::tm t0_tm;
|
||||
::localtime_r(&t0_time_t, &t0_tm);
|
||||
|
||||
/* midnight on the same calendar day as t0_tm */
|
||||
std::tm midnight_tm = t0_tm;
|
||||
{
|
||||
midnight_tm.tm_hour = 0;
|
||||
midnight_tm.tm_min = 0;
|
||||
midnight_tm.tm_sec = 0;
|
||||
}
|
||||
|
||||
/* convert local midnight to UTC epoch seconds */
|
||||
time_t midnight_time_t = ::timelocal(&midnight_tm);
|
||||
|
||||
utc_nanos t0_midnight =
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(
|
||||
std::chrono::system_clock::from_time_t(midnight_time_t)));
|
||||
|
||||
nanos t0_tdy = t0 - t0_midnight;
|
||||
|
||||
return std::pair<utc_nanos, nanos>(t0_midnight, t0_tdy);
|
||||
} /*local_split_vs_midnight*/
|
||||
|
||||
/* split utc_nanos into
|
||||
* std::tm
|
||||
* .tm_year
|
||||
* .tm_mon (1-12)
|
||||
* .tm_mday (1-31)
|
||||
* .tm_hour (0-23)
|
||||
* .tm_min (0-59)
|
||||
* .tm_sec (0-59)
|
||||
* .tm_wday (0=sunday .. 6=saturday)
|
||||
* .tm_yday (0=1jan .. 365)
|
||||
* .tm_isdst (daylight savings time flag)
|
||||
* usec (0-999999)
|
||||
*/
|
||||
static std::pair<std::tm, uint32_t> split_tm(utc_nanos t0) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
time_t t0_time_t = (std::chrono::system_clock::to_time_t
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(t0)));
|
||||
|
||||
/* convert to std::tm, un UTC coords,
|
||||
* only provides 1-second precision
|
||||
*/
|
||||
std::tm t0_tm;
|
||||
::gmtime_r(&t0_time_t, &t0_tm);
|
||||
|
||||
/* midnight on the same calendar day as t0_tm */
|
||||
std::tm midnight_tm = t0_tm;
|
||||
|
||||
midnight_tm.tm_isdst = 0;
|
||||
midnight_tm.tm_hour = 0;
|
||||
midnight_tm.tm_min = 0;
|
||||
midnight_tm.tm_sec = 0;
|
||||
|
||||
/* convert back to epoch seconds */
|
||||
time_t midnight_time_t = ::mktime(&midnight_tm);
|
||||
|
||||
utc_nanos t0_midnight =
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(
|
||||
std::chrono::system_clock::from_time_t(midnight_time_t)));
|
||||
|
||||
uint32_t usec =
|
||||
(std::chrono::duration_cast<microseconds>(
|
||||
std::chrono::hh_mm_ss(t0 - t0_midnight).subseconds()))
|
||||
.count();
|
||||
|
||||
return std::make_pair(t0_tm, usec);
|
||||
} /*split_tm*/
|
||||
|
||||
static void print_hms_msec(nanos dt, std::ostream & os) {
|
||||
/* use hhmmss.nnn */
|
||||
using std::int32_t;
|
||||
|
||||
auto hms = std::chrono::hh_mm_ss(dt);
|
||||
int32_t h = hms.hours().count();
|
||||
int32_t m = hms.minutes().count();
|
||||
int32_t s = hms.seconds().count();
|
||||
int32_t msec = std::chrono::duration_cast<milliseconds>(hms.subseconds()).count();
|
||||
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03d", h, m, s, msec);
|
||||
|
||||
os << buf;
|
||||
} /*print_hms_msec*/
|
||||
|
||||
static void print_utc_hms_msec(utc_nanos t0, std::ostream & os) {
|
||||
print_hms_msec(utc_split_vs_midnight(t0).second, os);
|
||||
} /*print_utc_hms_usec*/
|
||||
|
||||
static void print_hms_usec(nanos dt, std::ostream & os) {
|
||||
/* use hhmmss.uuuuuu */
|
||||
using std::int32_t;
|
||||
|
||||
auto hms = std::chrono::hh_mm_ss(dt);
|
||||
int32_t h = hms.hours().count();
|
||||
int32_t m = hms.minutes().count();
|
||||
int32_t s = hms.seconds().count();
|
||||
int32_t usec = std::chrono::duration_cast<microseconds>(hms.subseconds()).count();
|
||||
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06d", h, m, s, usec);
|
||||
|
||||
os << buf;
|
||||
} /*print_hms_usec*/
|
||||
|
||||
static void print_utc_ymd_hms_usec(utc_nanos t0, std::ostream & os) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
//std::tm t0_tm;
|
||||
//uint32_t t0_usec;
|
||||
|
||||
/* (structured binding ftw!) */
|
||||
auto [t0_tm, t0_usec] = split_tm(t0);
|
||||
|
||||
/* no std::format in clang11 afaict */
|
||||
char usec_buf[7];
|
||||
snprintf(usec_buf, sizeof(usec_buf), "%06d", t0_usec);
|
||||
|
||||
|
||||
/* control string | example
|
||||
* ----------------------------+--------------------------
|
||||
* %c - locale-specific string | Fri Jun 10 16:29:05 2022
|
||||
* %Y - year | 2022
|
||||
* %m - month | 06
|
||||
* %d - day of month | 10
|
||||
* %H - hour | 16
|
||||
* %M - minute | 29
|
||||
* %S - second | 05
|
||||
* %Z - timezone | UTC
|
||||
*/
|
||||
os << std::put_time(&t0_tm, "%Y%m%d:%H:%M:%S.") << usec_buf;
|
||||
} /*print_utc_ymd_hms_usec*/
|
||||
|
||||
/* print datetime in format compatible with ISO 8601.
|
||||
* copying the format javascript uses, e.g:
|
||||
* 2012-04-23T18:25:43.511Z
|
||||
*/
|
||||
static void print_iso8601(utc_nanos t0, std::ostream & os) {
|
||||
auto [t0_tm, t0_usec] = split_tm(t0);
|
||||
|
||||
char msec_buf[8];
|
||||
snprintf(msec_buf, sizeof(msec_buf), "%03d", t0_usec / 1000);
|
||||
|
||||
os << std::put_time(&t0_tm, "%Y-%m-%dT%H:%M:%S.") << msec_buf << "Z";
|
||||
} /*print_iso8601*/
|
||||
}; /*time*/
|
||||
// ----- iso8601 -----
|
||||
|
||||
/* stream inserter that displays time in ISO 8601 format:
|
||||
* 2012-04-23T18:25:43.511Z
|
||||
|
|
@ -294,18 +21,20 @@ namespace xo {
|
|||
operator<<(std::ostream & os,
|
||||
iso8601 x)
|
||||
{
|
||||
time::print_iso8601(x.t0_, os);
|
||||
timeutil::print_iso8601(x.t0_, os);
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
|
||||
// ----- hms_msec -----
|
||||
|
||||
/* stream inserter that display time like:
|
||||
* hh:mm:ss.nnn
|
||||
*/
|
||||
struct hms_msec {
|
||||
hms_msec(nanos dt) : dt_{dt} {}
|
||||
|
||||
static hms_msec utc(utc_nanos t0) { return hms_msec(time::utc_split_vs_midnight(t0).second); }
|
||||
static hms_msec local(utc_nanos t0) { return hms_msec(time::local_split_vs_midnight(t0).second); }
|
||||
static hms_msec utc(utc_nanos t0) { return hms_msec(timeutil::utc_split_vs_midnight(t0).second); }
|
||||
static hms_msec local(utc_nanos t0) { return hms_msec(timeutil::local_split_vs_midnight(t0).second); }
|
||||
|
||||
nanos dt_;
|
||||
}; /*hms_msec*/
|
||||
|
|
@ -313,10 +42,11 @@ namespace xo {
|
|||
inline std::ostream &
|
||||
operator<<(std::ostream & os, hms_msec x)
|
||||
{
|
||||
time::print_hms_msec(x.dt_, os);
|
||||
timeutil::print_hms_msec(x.dt_, os);
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
|
||||
// ----- hms_usec -----
|
||||
|
||||
/* stream inserter that display time like:
|
||||
* hh:mm:ss.nnnnnn
|
||||
|
|
@ -324,8 +54,8 @@ namespace xo {
|
|||
struct hms_usec {
|
||||
hms_usec(nanos dt) : dt_{dt} {}
|
||||
|
||||
static hms_usec utc(utc_nanos t0) { return hms_usec(time::utc_split_vs_midnight(t0).second); }
|
||||
static hms_usec local(utc_nanos t0) { return hms_usec(time::local_split_vs_midnight(t0).second); }
|
||||
static hms_usec utc(utc_nanos t0) { return hms_usec(timeutil::utc_split_vs_midnight(t0).second); }
|
||||
static hms_usec local(utc_nanos t0) { return hms_usec(timeutil::local_split_vs_midnight(t0).second); }
|
||||
|
||||
nanos dt_;
|
||||
}; /*hms_msec*/
|
||||
|
|
@ -333,11 +63,9 @@ namespace xo {
|
|||
inline std::ostream &
|
||||
operator<<(std::ostream & os, hms_usec x)
|
||||
{
|
||||
time::print_hms_usec(x.dt_, os);
|
||||
timeutil::print_hms_usec(x.dt_, os);
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
|
||||
|
||||
} /*namespace time*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
@ -346,14 +74,14 @@ namespace std {
|
|||
inline std::ostream & operator<<(std::ostream & os,
|
||||
xo::time::utc_nanos t0)
|
||||
{
|
||||
xo::time::time::print_utc_ymd_hms_usec(t0, os);
|
||||
xo::time::timeutil::print_utc_ymd_hms_usec(t0, os);
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & os,
|
||||
xo::time::nanos dt)
|
||||
{
|
||||
xo::time::time::print_hms_usec(dt, os);
|
||||
xo::time::timeutil::print_hms_usec(dt, os);
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
} /*namespace chrono*/
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace xo {
|
|||
# define XO_DEBUG(debug_flag) XO_ENTER1(always, debug_flag)
|
||||
# define XO_DEBUG2(debug_flag, name1) XO_ENTER2(always, debug_flag, name1)
|
||||
|
||||
# define XO_LITERAL(lvl, name1, name2) xo::scope_setup(xo::log_level::lvl, FS_Literal, name1, name2, __FILE__, __LINE__)
|
||||
# define XO_LITERAL(lvl, name1, name2) xo::scope_setup(xo::log_level::lvl, function_style::literal, name1, name2, __FILE__, __LINE__)
|
||||
|
||||
//# define XO_SSETUP0() xo::scope_setup(__FUNCTION__)
|
||||
//# define XO_SSETUP0(lvl) xo::scope_setup(xo::log_level::lvl, xo::log_config::style, __PRETTY_FUNCTION__, __FILE__, __LINE__)
|
||||
|
|
|
|||
287
include/indentlog/timeutil/timeutil.hpp
Normal file
287
include/indentlog/timeutil/timeutil.hpp
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
/* @file time.hpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#ifdef NOT_YET
|
||||
# include <format>
|
||||
#endif
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <time.h>
|
||||
|
||||
namespace xo {
|
||||
namespace time {
|
||||
|
||||
using utc_nanos = std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::nanoseconds>;
|
||||
|
||||
using nanos = std::chrono::nanoseconds;
|
||||
using microseconds = std::chrono::microseconds;
|
||||
using milliseconds = std::chrono::milliseconds;
|
||||
using seconds = std::chrono::seconds;
|
||||
using hours = std::chrono::hours;
|
||||
using days = std::chrono::days;
|
||||
|
||||
struct timeutil {
|
||||
static utc_nanos now() {
|
||||
return utc_nanos(std::chrono::system_clock::now());
|
||||
}
|
||||
|
||||
static utc_nanos epoch() {
|
||||
return utc_nanos(std::chrono::system_clock::from_time_t(0));
|
||||
} /*epoch*/
|
||||
|
||||
static utc_nanos ymd_hms(uint32_t ymd, uint32_t hms) {
|
||||
/* e.g. ymd=20220610 -> n_yr=2022, n_mon=06, n_dy=10 */
|
||||
|
||||
uint32_t n_yr = ymd / 10000;
|
||||
uint32_t n_mon = (ymd % 10000) / 100;
|
||||
uint32_t n_dy = ymd % 100;
|
||||
|
||||
uint32_t n_hr = hms / 10000;
|
||||
uint32_t n_min = (hms % 10000) / 100;
|
||||
uint32_t n_sec = hms % 100;
|
||||
|
||||
struct tm t;
|
||||
|
||||
t.tm_year = n_yr - 1900; /* 0 means 1900 */
|
||||
t.tm_mon = n_mon - 1; /* 0 means january */
|
||||
t.tm_mday = n_dy;
|
||||
|
||||
t.tm_hour = n_hr; /* 24 hour clock */
|
||||
t.tm_min = n_min;
|
||||
t.tm_sec = n_sec;
|
||||
|
||||
/* time since epoch */
|
||||
time_t epoch_time = timegm(&t);
|
||||
|
||||
return std::chrono::system_clock::from_time_t(epoch_time);
|
||||
} /*ymd_hms*/
|
||||
|
||||
/* midnight UTC on date ymd.
|
||||
* e.g. ymd_midnight(20220707) -> midnight UTC on 7jul22
|
||||
*/
|
||||
static utc_nanos ymd_midnight(uint32_t ymd) {
|
||||
return ymd_hms(ymd, 0);
|
||||
} /*ymd_midnight*/
|
||||
|
||||
static utc_nanos ymd_hms_usec(uint32_t ymd, uint32_t hms, uint32_t usec) {
|
||||
utc_nanos s = ymd_hms(ymd, hms);
|
||||
|
||||
return s + microseconds(usec);
|
||||
} /*ymd_hms_usec*/
|
||||
|
||||
/* .first: UTC midnight on same calendar day as t0
|
||||
* .second: elapsed time from .first to t0 (i.e. UTC time-of-day for t0)
|
||||
*/
|
||||
static std::pair<utc_nanos, nanos> utc_split_vs_midnight(utc_nanos t0) {
|
||||
//using xo::timeutil::microseconds;
|
||||
//using xo::timeutil::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
time_t t0_time_t = (std::chrono::system_clock::to_time_t
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(t0)));
|
||||
|
||||
/* convert to std::tm,
|
||||
* only provides 1-second precision
|
||||
*/
|
||||
std::tm t0_tm;
|
||||
::gmtime_r(&t0_time_t, &t0_tm);
|
||||
|
||||
/* midnight on the same calendar day as t0_tm */
|
||||
std::tm midnight_tm = t0_tm;
|
||||
{
|
||||
midnight_tm.tm_hour = 0;
|
||||
midnight_tm.tm_min = 0;
|
||||
midnight_tm.tm_sec = 0;
|
||||
}
|
||||
|
||||
/* convert to UTC epoch seconds */
|
||||
time_t midnight_time_t = ::timegm(&midnight_tm);
|
||||
|
||||
utc_nanos t0_midnight =
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(
|
||||
std::chrono::system_clock::from_time_t(midnight_time_t)));
|
||||
|
||||
nanos t0_tdy = t0 - t0_midnight;
|
||||
|
||||
return std::pair<utc_nanos, nanos>(t0_midnight, t0_tdy);
|
||||
} /*utc_split_vs_midnight*/
|
||||
|
||||
/* .first: LOCAL midnight on same calendar day as t0 (but in UTC coords)
|
||||
* .second: elapsed time from .first to t0 (i.e. LOCAL time-of-day for t0)
|
||||
*/
|
||||
static std::pair<utc_nanos, nanos> local_split_vs_midnight(utc_nanos t0) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
time_t t0_time_t = (std::chrono::system_clock::to_time_t
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(t0)));
|
||||
|
||||
/* convert to std::tm,
|
||||
* only provides 1-second precision
|
||||
*/
|
||||
std::tm t0_tm;
|
||||
::localtime_r(&t0_time_t, &t0_tm);
|
||||
|
||||
/* midnight on the same calendar day as t0_tm */
|
||||
std::tm midnight_tm = t0_tm;
|
||||
{
|
||||
midnight_tm.tm_hour = 0;
|
||||
midnight_tm.tm_min = 0;
|
||||
midnight_tm.tm_sec = 0;
|
||||
}
|
||||
|
||||
/* convert local midnight to UTC epoch seconds */
|
||||
time_t midnight_time_t = ::timelocal(&midnight_tm);
|
||||
|
||||
utc_nanos t0_midnight =
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(
|
||||
std::chrono::system_clock::from_time_t(midnight_time_t)));
|
||||
|
||||
nanos t0_tdy = t0 - t0_midnight;
|
||||
|
||||
return std::pair<utc_nanos, nanos>(t0_midnight, t0_tdy);
|
||||
} /*local_split_vs_midnight*/
|
||||
|
||||
/* split utc_nanos into
|
||||
* std::tm
|
||||
* .tm_year
|
||||
* .tm_mon (1-12)
|
||||
* .tm_mday (1-31)
|
||||
* .tm_hour (0-23)
|
||||
* .tm_min (0-59)
|
||||
* .tm_sec (0-59)
|
||||
* .tm_wday (0=sunday .. 6=saturday)
|
||||
* .tm_yday (0=1jan .. 365)
|
||||
* .tm_isdst (daylight savings time flag)
|
||||
* usec (0-999999)
|
||||
*/
|
||||
static std::pair<std::tm, uint32_t> split_tm(utc_nanos t0) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
time_t t0_time_t = (std::chrono::system_clock::to_time_t
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(t0)));
|
||||
|
||||
/* convert to std::tm, un UTC coords,
|
||||
* only provides 1-second precision
|
||||
*/
|
||||
std::tm t0_tm;
|
||||
::gmtime_r(&t0_time_t, &t0_tm);
|
||||
|
||||
/* midnight on the same calendar day as t0_tm */
|
||||
std::tm midnight_tm = t0_tm;
|
||||
|
||||
midnight_tm.tm_isdst = 0;
|
||||
midnight_tm.tm_hour = 0;
|
||||
midnight_tm.tm_min = 0;
|
||||
midnight_tm.tm_sec = 0;
|
||||
|
||||
/* convert back to epoch seconds */
|
||||
time_t midnight_time_t = ::mktime(&midnight_tm);
|
||||
|
||||
utc_nanos t0_midnight =
|
||||
(std::chrono::time_point_cast<xo::time::microseconds>(
|
||||
std::chrono::system_clock::from_time_t(midnight_time_t)));
|
||||
|
||||
uint32_t usec =
|
||||
(std::chrono::duration_cast<microseconds>(
|
||||
std::chrono::hh_mm_ss(t0 - t0_midnight).subseconds()))
|
||||
.count();
|
||||
|
||||
return std::make_pair(t0_tm, usec);
|
||||
} /*split_tm*/
|
||||
|
||||
static void print_hms_msec(nanos dt, std::ostream & os) {
|
||||
/* use hhmmss.nnn */
|
||||
using std::int32_t;
|
||||
|
||||
auto hms = std::chrono::hh_mm_ss(dt);
|
||||
int32_t h = hms.hours().count();
|
||||
int32_t m = hms.minutes().count();
|
||||
int32_t s = hms.seconds().count();
|
||||
int32_t msec = std::chrono::duration_cast<milliseconds>(hms.subseconds()).count();
|
||||
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03d", h, m, s, msec);
|
||||
|
||||
os << buf;
|
||||
} /*print_hms_msec*/
|
||||
|
||||
static void print_utc_hms_msec(utc_nanos t0, std::ostream & os) {
|
||||
print_hms_msec(utc_split_vs_midnight(t0).second, os);
|
||||
} /*print_utc_hms_usec*/
|
||||
|
||||
static void print_hms_usec(nanos dt, std::ostream & os) {
|
||||
/* use hhmmss.uuuuuu */
|
||||
using std::int32_t;
|
||||
|
||||
auto hms = std::chrono::hh_mm_ss(dt);
|
||||
int32_t h = hms.hours().count();
|
||||
int32_t m = hms.minutes().count();
|
||||
int32_t s = hms.seconds().count();
|
||||
int32_t usec = std::chrono::duration_cast<microseconds>(hms.subseconds()).count();
|
||||
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06d", h, m, s, usec);
|
||||
|
||||
os << buf;
|
||||
} /*print_hms_usec*/
|
||||
|
||||
static void print_utc_ymd_hms_usec(utc_nanos t0, std::ostream & os) {
|
||||
using xo::time::microseconds;
|
||||
using xo::time::utc_nanos;
|
||||
|
||||
/* use yyyymmdd.hh:mm:ss.nnnnnn */
|
||||
|
||||
//std::tm t0_tm;
|
||||
//uint32_t t0_usec;
|
||||
|
||||
/* (structured binding ftw!) */
|
||||
auto [t0_tm, t0_usec] = split_tm(t0);
|
||||
|
||||
/* no std::format in clang11 afaict */
|
||||
char usec_buf[7];
|
||||
snprintf(usec_buf, sizeof(usec_buf), "%06d", t0_usec);
|
||||
|
||||
|
||||
/* control string | example
|
||||
* ----------------------------+--------------------------
|
||||
* %c - locale-specific string | Fri Jun 10 16:29:05 2022
|
||||
* %Y - year | 2022
|
||||
* %m - month | 06
|
||||
* %d - day of month | 10
|
||||
* %H - hour | 16
|
||||
* %M - minute | 29
|
||||
* %S - second | 05
|
||||
* %Z - timezone | UTC
|
||||
*/
|
||||
os << std::put_time(&t0_tm, "%Y%m%d:%H:%M:%S.") << usec_buf;
|
||||
} /*print_utc_ymd_hms_usec*/
|
||||
|
||||
/* print datetime in format compatible with ISO 8601.
|
||||
* copying the format javascript uses, e.g:
|
||||
* 2012-04-23T18:25:43.511Z
|
||||
*/
|
||||
static void print_iso8601(utc_nanos t0, std::ostream & os) {
|
||||
auto [t0_tm, t0_usec] = split_tm(t0);
|
||||
|
||||
char msec_buf[8];
|
||||
snprintf(msec_buf, sizeof(msec_buf), "%03d", t0_usec / 1000);
|
||||
|
||||
os << std::put_time(&t0_tm, "%Y-%m-%dT%H:%M:%S.") << msec_buf << "Z";
|
||||
} /*print_iso8601*/
|
||||
}; /*timeutil*/
|
||||
|
||||
} /*namespace time*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end timeutil.hpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue