From 75c59ed3bacec12b307ebd167b73c507168c1174 Mon Sep 17 00:00:00 2001 From: Adam Burgess Date: Wed, 26 Aug 2020 04:45:06 +1000 Subject: [PATCH] Add formatters for chrono::time_point and helper overloads for localtime/gmtime(time_point) Fixes #1819 --- include/fmt/chrono.h | 21 +++++++++++++++++++++ test/chrono-test.cc | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index e70b8053..07af8d68 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -351,6 +351,11 @@ inline std::tm localtime(std::time_t time) { return lt.tm_; } +inline std::tm localtime( + std::chrono::time_point time_point) { + return localtime(std::chrono::system_clock::to_time_t(time_point)); +} + // Thread-safe replacement for std::gmtime inline std::tm gmtime(std::time_t time) { struct dispatcher { @@ -387,6 +392,11 @@ inline std::tm gmtime(std::time_t time) { return gt.tm_; } +inline std::tm gmtime( + std::chrono::time_point time_point) { + return gmtime(std::chrono::system_clock::to_time_t(time_point)); +} + namespace detail { inline size_t strftime(char* str, size_t count, const char* format, const std::tm* time) { @@ -399,6 +409,17 @@ inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format, } } // namespace detail +template +struct formatter, Char> + : formatter { + template + auto format(std::chrono::time_point val, + FormatContext& ctx) -> decltype(ctx.out()) { + std::tm time = localtime(val); + return formatter::format(time, ctx); + } +}; + template struct formatter { template auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { diff --git a/test/chrono-test.cc b/test/chrono-test.cc index b876c151..a7065f76 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -95,6 +95,28 @@ TEST(TimeTest, GMTime) { EXPECT_TRUE(EqualTime(tm, fmt::gmtime(t))); } +TEST(TimeTest, TimePoint) { + setenv("TZ", "EST+5", 1); + tzset(); + std::chrono::system_clock::time_point point(std::chrono::seconds(1598412345)); + EXPECT_EQ("It is 2020-08-25 22:25:45.", + fmt::format("It is {:%Y-%m-%d %H:%M:%S}.", point)); +} + +TEST(TimeTest, LocalTimeWithTimePoint) { + setenv("TZ", "EST+5", 1); + tzset(); + std::chrono::system_clock::time_point point(std::chrono::seconds(1598412345)); + EXPECT_EQ("It is 2020-08-25 22:25:45.", + fmt::format("It is {:%Y-%m-%d %H:%M:%S}.", fmt::localtime(point))); +} + +TEST(TimeTest, GMTimeWithTimePoint) { + std::chrono::system_clock::time_point point(std::chrono::seconds(1598412345)); + EXPECT_EQ("It is 2020-08-26 03:25:45 UTC.", + fmt::format("It is {:%Y-%m-%d %H:%M:%S} UTC.", fmt::gmtime(point))); +} + #define EXPECT_TIME(spec, time, duration) \ { \ std::locale loc("ja_JP.utf8"); \