diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index ed7f5f16..1a8d8d04 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -22,6 +22,15 @@ FMT_BEGIN_NAMESPACE +// Check if std::chrono::utc_timestamp is available. +#ifndef FMT_USE_UTC_TIME +# ifdef __cpp_lib_chrono +# define FMT_USE_UTC_TIME (__cpp_lib_chrono >= 201907L) +# else +# define FMT_USE_UTC_TIME 0 +# endif +#endif + // Enable tzset. #ifndef FMT_USE_TZSET // UWP doesn't provide _tzset. @@ -2014,6 +2023,25 @@ struct formatter, } }; +#if FMT_USE_UTC_TIME +template +struct formatter, + Char> : formatter { + FMT_CONSTEXPR formatter() { + basic_string_view default_specs = + detail::string_literal{}; + this->do_parse(default_specs.begin(), default_specs.end()); + } + + template + auto format(std::chrono::time_point val, + FormatContext& ctx) const -> decltype(ctx.out()) { + return formatter::format( + localtime(std::chrono::utc_clock::to_sys(val)), ctx); + } +}; +#endif + template struct formatter { private: enum class spec { diff --git a/test/chrono-test.cc b/test/chrono-test.cc index 0f2a2498..bc474a40 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -641,3 +641,14 @@ TEST(chrono_test, cpp20_duration_subsecond_support) { } #endif // FMT_STATIC_THOUSANDS_SEPARATOR + +// Disable the utc_clock test for windows, as the icu.dll used for tzdb +// (time zone database) is not shipped with many windows versions. +#if FMT_USE_UTC_TIME && !defined(_WIN32) +TEST(chrono_test, utc_clock) { + auto t1 = std::chrono::system_clock::now(); + auto t1_utc = std::chrono::utc_clock::from_sys(t1); + EXPECT_EQ(fmt::format("{:%Y-%m-%d %H:%M:%S}", t1), + fmt::format("{:%Y-%m-%d %H:%M:%S}", t1_utc)); +} +#endif