@@ -265,6 +265,15 @@ using utc_time = std::chrono::time_point<detail::utc_clock, Duration>;
265265template <class Duration >
266266using local_time = std::chrono::time_point<detail::local_t , Duration>;
267267
268+ // Check if std::chrono::zoned_time is available.
269+ #ifdef FMT_HAVE_STD_ZONED_TIME
270+ // Use the provided definition.
271+ #elif defined(__cpp_lib_chrono)
272+ # define FMT_HAVE_STD_ZONED_TIME (__cpp_lib_chrono >= 201907L )
273+ #else
274+ # define FMT_HAVE_STD_ZONED_TIME 0
275+ #endif
276+
268277namespace detail {
269278
270279// Prevents expansion of a preceding token as a function-style macro.
@@ -2240,6 +2249,42 @@ struct formatter<local_time<Duration>, Char>
22402249 }
22412250};
22422251
2252+ #if FMT_HAVE_STD_ZONED_TIME
2253+ template <typename Duration, typename TimeZonePtr, typename Char>
2254+ struct formatter <std::chrono::zoned_time<Duration, TimeZonePtr>, Char,
2255+ std::enable_if_t <std::is_pointer_v<TimeZonePtr>>>
2256+ : private formatter<std::tm, Char> {
2257+ FMT_CONSTEXPR auto parse (parse_context<Char>& ctx) -> const Char* {
2258+ return this ->do_parse (ctx, true );
2259+ }
2260+
2261+ template <typename FormatContext>
2262+ auto format (const std::chrono::zoned_time<Duration, TimeZonePtr>& val,
2263+ FormatContext& ctx) const -> decltype(ctx.out()) {
2264+ auto time_info = val.get_info ();
2265+ auto time_since_epoch = val.get_local_time ().time_since_epoch ();
2266+ auto seconds_since_epoch =
2267+ detail::duration_cast<std::chrono::seconds>(time_since_epoch);
2268+ // Use gmtime to prevent time zone conversion since local_time has an
2269+ // unspecified time zone.
2270+ std::tm t = gmtime (seconds_since_epoch.count ());
2271+ // Create a custom tm with timezone info if supported
2272+ if constexpr (detail::has_tm_zone<std::tm>::value) {
2273+ t.tm_zone = time_info.abbrev .c_str ();
2274+ t.tm_gmtoff = time_info.offset .count ();
2275+ }
2276+ using period = typename Duration::period;
2277+ if (period::num == 1 && period::den == 1 &&
2278+ !std::is_floating_point<typename Duration::rep>::value) {
2279+ return formatter<std::tm, Char>::format (t, ctx);
2280+ }
2281+ auto subsecs =
2282+ detail::duration_cast<Duration>(time_since_epoch - seconds_since_epoch);
2283+ return formatter<std::tm, Char>::do_format (t, ctx, &subsecs);
2284+ }
2285+ };
2286+ #endif
2287+
22432288FMT_END_EXPORT
22442289FMT_END_NAMESPACE
22452290
0 commit comments