Skip to content

Commit 94381c8

Browse files
committed
zoned_time
1 parent 0e078f6 commit 94381c8

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

include/fmt/chrono.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,20 @@ using utc_time = std::chrono::time_point<detail::utc_clock, Duration>;
265265
template <class Duration>
266266
using 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_TEST
270+
// Use the provided definition.
271+
#elif defined(__cpp_lib_chrono)
272+
# define FMT_HAVE_STD_ZONED_TIME_TEST (__cpp_lib_chrono >= 201907L)
273+
#else
274+
# define FMT_HAVE_STD_ZONED_TIME_TEST 0
275+
#endif
276+
277+
#if FMT_HAVE_STD_ZONED_TIME_TEST
278+
template <typename Duration, typename TimeZonePtr>
279+
using zoned_time = std::chrono::zoned_time<Duration, TimeZonePtr>;
280+
#endif
281+
268282
namespace detail {
269283

270284
// Prevents expansion of a preceding token as a function-style macro.
@@ -2240,6 +2254,42 @@ struct formatter<local_time<Duration>, Char>
22402254
}
22412255
};
22422256

2257+
#if FMT_HAVE_STD_ZONED_TIME_TEST
2258+
template <typename Duration, typename TimeZonePtr, typename Char>
2259+
struct formatter<zoned_time<Duration, TimeZonePtr>, Char,
2260+
std::enable_if_t<std::is_pointer_v<TimeZonePtr>>>
2261+
: private formatter<std::tm, Char> {
2262+
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
2263+
return this->do_parse(ctx, true);
2264+
}
2265+
2266+
template <typename FormatContext>
2267+
auto format(const std::chrono::zoned_time<Duration, TimeZonePtr>& val,
2268+
FormatContext& ctx) const -> decltype(ctx.out()) {
2269+
auto time_info = val.get_info();
2270+
auto time_since_epoch = val.get_local_time().time_since_epoch();
2271+
auto seconds_since_epoch =
2272+
detail::duration_cast<std::chrono::seconds>(time_since_epoch);
2273+
// Use gmtime to prevent time zone conversion since local_time has an
2274+
// unspecified time zone.
2275+
std::tm t = gmtime(seconds_since_epoch.count());
2276+
// Create a custom tm with timezone info if supported
2277+
if constexpr (detail::has_tm_zone<std::tm>::value) {
2278+
t.tm_zone = time_info.abbrev.c_str();
2279+
t.tm_gmtoff = time_info.offset.count();
2280+
}
2281+
using period = typename Duration::period;
2282+
if (period::num == 1 && period::den == 1 &&
2283+
!std::is_floating_point<typename Duration::rep>::value) {
2284+
return formatter<std::tm, Char>::format(t, ctx);
2285+
}
2286+
auto subsecs =
2287+
detail::duration_cast<Duration>(time_since_epoch - seconds_since_epoch);
2288+
return formatter<std::tm, Char>::do_format(t, ctx, &subsecs);
2289+
}
2290+
};
2291+
#endif
2292+
22432293
FMT_END_EXPORT
22442294
FMT_END_NAMESPACE
22452295

0 commit comments

Comments
 (0)