From c64dff02db93eee2f0fb0c4b95cc5719af9ce3a2 Mon Sep 17 00:00:00 2001 From: Dirk Vanden Boer Date: Tue, 27 Aug 2024 15:58:23 +0200 Subject: [PATCH] UTC conversion improvements --- chrono.cpp | 27 +++++++++++++++------------ chrono.natvis | 26 +++----------------------- include/infra/chrono.h | 28 +++++++++++++++++++--------- 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/chrono.cpp b/chrono.cpp index aad0d412..9c17fc4d 100644 --- a/chrono.cpp +++ b/chrono.cpp @@ -175,30 +175,33 @@ std::optional local_time_point_from_string(std::string_view st } #ifdef HAVE_CPP20_CHRONO -std::optional localtime_to_utc(time_point dt, std::chrono::choose* choice) +std::optional localtime_to_utc(local_time_point dt, std::optional choice) { - auto ymd = chrono::to_year_month_day(dt); - auto tod = chrono::time_of_day(dt); // Yields time_of_day type + if (choice.has_value()) { + return localtime_to_utc(zoned_time(std::chrono::current_zone(), dt, *choice)); + } else { + return localtime_to_utc(zoned_time(std::chrono::current_zone(), dt)); + } +} - auto tp = std::chrono::local_days{ymd} + tod.hours() + tod.minutes() + tod.seconds(); - auto z = std::chrono::current_zone(); +std::optional localtime_to_utc(zoned_time zt) +{ + auto localTimePoint = zt.get_local_time(); std::optional utcTime; - auto i = z->get_info(tp); + auto i = zt.get_time_zone()->get_info(localTimePoint); switch (i.result) { case std::chrono::local_info::unique: { - std::chrono::zoned_time zt(z, tp); //"Europe/Brussels" utcTime = std::optional(zt.get_sys_time()); break; } case std::chrono::local_info::ambiguous: { - if (choice) { - std::chrono::zoned_time zt(z, tp, *choice); - utcTime = std::optional(zt.get_sys_time()); - } + Log::warn("Ambiguous time point, taking the latest option"); + utcTime = std::optional(i.second.begin); break; } case std::chrono::local_info::nonexistent: + Log::error("Non existing timepoint"); break; default: break; @@ -207,7 +210,7 @@ std::optional localtime_to_utc(time_point dt, std::chrono::choose* c return utcTime; } #else -std::optional localtime_to_utc(time_point dt, date::choose* choice) +std::optional localtime_to_utc(local_time_point dt, std::optional choice) { auto ymd = chrono::to_year_month_day(dt); auto tod = chrono::time_of_day(dt); // Yields time_of_day type diff --git a/chrono.natvis b/chrono.natvis index 1c281ea3..52ec02a0 100644 --- a/chrono.natvis +++ b/chrono.natvis @@ -1,31 +1,11 @@ - - year: { - 1969 + - 4 * (((_MyDur._MyRep / (24 * 60 * 60 * 10000000ull)) + 365) / (365 * 3 + 366)) + - (((_MyDur._MyRep / (24 * 60 * 60 * 10000000ull)) + 365) % (365 * 3 + 366) <= (3 * 365) ? (((_MyDur._MyRep / (24 * 60 * 60 * 10000000ull)) + 365) % (365 * 3 + 366)) / 365 : 3) - } DoY: { - ((_MyDur._MyRep / (24 * 60 * 60 * 10000000ull)) + 365) % (365 * 3 + 366) <= (3 * 365) ? (((_MyDur._MyRep / (24 * 60 * 60 * 10000000ull)) + 365) % (365 * 3 + 366)) % 365 : (((_MyDur._MyRep / (24 * 60 * 60 * 10000000ull)) + 365) % (365 * 3 + 366)) - 365 * 3 - } { - (_MyDur._MyRep % (24 * 60 * 60 * 10000000ull))/(10 * 60 * 60 * 10000000ull)}{(_MyDur._MyRep % (4 * 60 * 60 * 10000000ull))/(60 * 60 * 10000000ull)}:{(_MyDur._MyRep % (60 * 60 * 10000000ull))/(10 * 60 * 10000000ull)}{(_MyDur._MyRep % (10 * 60 * 10000000ull)) / (60 * 10000000ull)}:{(_MyDur._MyRep % (60 * 10000000ull)) / (10 * 10000000ull)}{(_MyDur._MyRep % (10 * 10000000ull)) / 10000000ull}.{(_MyDur._MyRep % 10000000) / 1000000}{(_MyDur._MyRep % 1000000) / 100000}{(_MyDur._MyRep % 100000) / 10000}{(_MyDur._MyRep % 10000) / 1000}{(_MyDur._MyRep % 1000) / 100}{(_MyDur._MyRep % 100) / 10}{_MyDur._MyRep % 10 - } hh:mm:ss - - + + {1968+4*((_MyDur._MyRep/864000000000ll+731)/1461)+((((_MyDur._MyRep/864000000000ll+731)%1461)<366)?0:(((_MyDur._MyRep/864000000000ll+731)%1461-1)/365))}/{char(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365+(((((_MyDur._MyRep/864000000000ll)+731)%1461)<366)?1:0))/31+1):(3+(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)/153)*5+(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)%153)/61*2+(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)%153)%61/31))%10+((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365+(((((_MyDur._MyRep/864000000000ll)+731)%1461)<366)?1:0))/31+1):(3+(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)/153)*5+(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)%153)/61*2+(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)%153)%61/31))/10*16),nvoxb}/{char(((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365+(((((_MyDur._MyRep/864000000000ll)+731)%1461)<366)?1:0))%31+1):((((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)%153)%61%31+1))%10+((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365+(((((_MyDur._MyRep/864000000000ll)+731)%1461)<366)?1:0))%31+1):((((((_MyDur._MyRep/864000000000ll+731)%1461-1)%365)-59)%153)%61%31+1))/10*16),nvoxb} {char(((_MyDur._MyRep/36000000000ll)%24)%10+((_MyDur._MyRep/36000000000ll)%24)/10*16),nvoxb}:{char(((_MyDur._MyRep/600000000ll)%60)%10+((_MyDur._MyRep/600000000ll)%60)/10*16),nvoxb}:{char(((_MyDur._MyRep/10000000ll)%60)%10+((_MyDur._MyRep/10000000ll)%60)/10*16),nvoxb}.{short((_MyDur._MyRep/1000)%10+((_MyDur._MyRep/10000)%10)*16+((_MyDur._MyRep/100000)%10)*256+((_MyDur._MyRep/1000000)%10)*4096),nvoxb} - - year: { - 1969 + - 4 * (((_MyDur._MyRep / (24 * 60 * 60 * 1000ull)) + 365) / (365 * 3 + 366)) + - (((_MyDur._MyRep / (24 * 60 * 60 * 1000ull)) + 365) % (365 * 3 + 366) <= (3 * 365) ? (((_MyDur._MyRep / (24 * 60 * 60 * 1000ull)) + 365) % (365 * 3 + 366)) / 365 : 3) - } DoY: { - ((_MyDur._MyRep / (24 * 60 * 60 * 1000ull)) + 365) % (365 * 3 + 366) <= (3 * 365) ? (((_MyDur._MyRep / (24 * 60 * 60 * 1000ull)) + 365) % (365 * 3 + 366)) % 365 : (((_MyDur._MyRep / (24 * 60 * 60 * 1000ull)) + 365) % (365 * 3 + 366)) - 365 * 3 - } { - (_MyDur._MyRep % (24 * 60 * 60 * 1000ull))/(10 * 60 * 60 * 1000ull)}{(_MyDur._MyRep % (4 * 60 * 60 * 1000ull))/(60 * 60 * 1000ull)}:{(_MyDur._MyRep % (60 * 60 * 1000ull))/(10 * 60 * 1000ull)}{(_MyDur._MyRep % (10 * 60 * 1000ull)) / (60 * 1000ull)}:{(_MyDur._MyRep % (60 * 1000ull)) / (10 * 1000ull)}{(_MyDur._MyRep % (10 * 1000ull)) / 1000ull}.{(_MyDur._MyRep % 1000) / 100}{(_MyDur._MyRep % 100) / 10 - } hh:mm:ss - + {1968+4*((_MyDur._MyRep/86400000ll+731)/1461)+((((_MyDur._MyRep/86400000ll+731)%1461)<366)?0:(((_MyDur._MyRep/86400000ll+731)%1461-1)/365))}/{char(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/86400000ll+731)%1461-1)%365+(((((_MyDur._MyRep/86400000ll)+731)%1461)<366)?1:0))/31+1):(3+(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)/153)*5+(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)%153)/61*2+(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)%153)%61/31))%10+((((_MyDur._MyRep/86400000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/86400000ll+731)%1461-1)%365+(((((_MyDur._MyRep/86400000ll)+731)%1461)<366)?1:0))/31+1):(3+(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)/153)*5+(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)%153)/61*2+(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)%153)%61/31))/10*16),nvoxb}/{char(((((_MyDur._MyRep/86400000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/86400000ll+731)%1461-1)%365+(((((_MyDur._MyRep/86400000ll)+731)%1461)<366)?1:0))%31+1):((((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)%153)%61%31+1))%10+((((_MyDur._MyRep/86400000ll+731)%1461-1)%365<59)?((((_MyDur._MyRep/86400000ll+731)%1461-1)%365+(((((_MyDur._MyRep/86400000ll)+731)%1461)<366)?1:0))%31+1):((((((_MyDur._MyRep/86400000ll+731)%1461-1)%365)-59)%153)%61%31+1))/10*16),nvoxb} {char(((_MyDur._MyRep/3600000ll)%24)%10+((_MyDur._MyRep/3600000ll)%24)/10*16),nvoxb}:{char(((_MyDur._MyRep/60000ll)%60)%10+((_MyDur._MyRep/60000ll)%60)/10*16),nvoxb}:{char(((_MyDur._MyRep/1000ll)%60)%10+((_MyDur._MyRep/1000ll)%60)/10*16),nvoxb}.{short((_MyDur._MyRep/1000)%10+((_MyDur._MyRep/10000)%10)*16+((_MyDur._MyRep/100000)%10)*256+((_MyDur._MyRep/1000000)%10)*4096),nvoxb} diff --git a/include/infra/chrono.h b/include/infra/chrono.h index 07b952bd..ab9a40f1 100644 --- a/include/infra/chrono.h +++ b/include/infra/chrono.h @@ -30,6 +30,8 @@ using year_month_day = std::chrono::year_month_day; using sys_days = std::chrono::sys_days; using date_point = std::chrono::time_point; using time_point = std::chrono::time_point; +using zoned_time = std::chrono::zoned_time; +using utc_clock = std::chrono::utc_clock; using local_seconds = std::chrono::local_seconds; using local_date_point = std::chrono::local_days; @@ -57,6 +59,8 @@ using year_month_day = date::year_month_day; using sys_days = date::sys_days; using date_point = std::chrono::time_point; using time_point = std::chrono::time_point; +using zoned_time = date::zoned_time; +using utc_clock = date::utc_clock; using local_seconds = date::local_seconds; using local_date_point = date::local_days; @@ -88,6 +92,7 @@ local_date_point date_from_time_point(local_time_point tp); #ifdef HAVE_CPP20_CHRONO std::chrono::hh_mm_ss time_of_day(time_point tp); std::chrono::hh_mm_ss time_of_day(local_time_point tp); + std::chrono::year_month_day to_year_month_day(time_point tp); std::chrono::year_month_day to_year_month_day(local_time_point tp); @@ -134,8 +139,13 @@ std::string to_string(local_time_point tp); template std::string to_string(std::string_view format, std::chrono::time_point tp) { - std::time_t time = Clock::to_time_t(tp); - return fmt::format(fmt::runtime(fmt::format("{{:{}}}", format)), fmt::localtime(time)); + if constexpr (std::is_same_v) { + std::time_t time = std::chrono::system_clock::to_time_t(utc_clock::to_sys(tp)); + return fmt::format(fmt::runtime(fmt::format("{{:{}}}", format)), tp); + } else { + std::time_t time = Clock::to_time_t(tp); + return fmt::format(fmt::runtime(fmt::format("{{:{}}}", format)), fmt::localtime(time)); + } } /*! Converts a string to a time point using the provided format specification @@ -157,8 +167,11 @@ std::string to_utc_string(std::chrono::time_point tp) template std::string to_utc_string(std::string_view format, std::chrono::time_point tp) { - std::time_t time = Clock::to_time_t(tp); - return fmt::format(fmt::runtime(fmt::format("{{:{}}}", format)), fmt::gmtime(time)); + if constexpr (std::is_same_v) { + return fmt::format(fmt::runtime(fmt::format("{{:{}}}", format)), tp); + } else { + return fmt::format(fmt::runtime(fmt::format("{{:{}}}", format)), fmt::gmtime(tp)); + } } inline std::string to_string(std::string_view format, chrono::local_time_point tp) @@ -172,11 +185,8 @@ inline std::string to_string(std::string_view format, chrono::local_time_point t #endif } -#ifdef HAVE_CPP20_CHRONO -std::optional localtime_to_utc(time_point dt, std::chrono::choose* choice = nullptr); -#else -std::optional localtime_to_utc(time_point dt, date::choose* choice = nullptr); -#endif +std::optional localtime_to_utc(local_time_point dt, std::optional choice); +std::optional localtime_to_utc(zoned_time tp); class DurationRecorder {