@@ -265,6 +265,9 @@ 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+ template <typename Duration, typename TimeZonePtr>
269+ using zoned_time = std::chrono::zoned_time<Duration, TimeZonePtr>;
270+
268271namespace detail {
269272
270273// Prevents expansion of a preceding token as a function-style macro.
@@ -2240,6 +2243,40 @@ struct formatter<local_time<Duration>, Char>
22402243 }
22412244};
22422245
2246+ template <typename Duration, typename TimeZonePtr, typename Char>
2247+ struct formatter <zoned_time<Duration, TimeZonePtr>, Char,
2248+ std::enable_if_t <std::is_pointer_v<TimeZonePtr>>>
2249+ : private formatter<std::tm, Char> {
2250+ FMT_CONSTEXPR auto parse (parse_context<Char>& ctx) -> const Char* {
2251+ return this ->do_parse (ctx, true );
2252+ }
2253+
2254+ template <typename FormatContext>
2255+ auto format (const std::chrono::zoned_time<Duration, TimeZonePtr>& val,
2256+ FormatContext& ctx) const -> decltype(ctx.out()) {
2257+ auto time_info = val.get_info ();
2258+ auto time_since_epoch = val.get_local_time ().time_since_epoch ();
2259+ auto seconds_since_epoch =
2260+ detail::duration_cast<std::chrono::seconds>(time_since_epoch);
2261+ // Use gmtime to prevent time zone conversion since local_time has an
2262+ // unspecified time zone.
2263+ std::tm t = gmtime (seconds_since_epoch.count ());
2264+ // Create a custom tm with timezone info if supported
2265+ if constexpr (detail::has_tm_zone<std::tm>::value) {
2266+ t.tm_zone = time_info.abbrev .c_str ();
2267+ t.tm_gmtoff = time_info.offset .count ();
2268+ }
2269+ using period = typename Duration::period;
2270+ if (period::num == 1 && period::den == 1 &&
2271+ !std::is_floating_point<typename Duration::rep>::value) {
2272+ return formatter<std::tm, Char>::format (t, ctx);
2273+ }
2274+ auto subsecs =
2275+ detail::duration_cast<Duration>(time_since_epoch - seconds_since_epoch);
2276+ return formatter<std::tm, Char>::do_format (t, ctx, &subsecs);
2277+ }
2278+ };
2279+
22432280FMT_END_EXPORT
22442281FMT_END_NAMESPACE
22452282
0 commit comments