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