microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
boost_time.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
9#include "../microfmt.hpp"
10#include <boost/chrono.hpp>
11#include <boost/date_time/gregorian/gregorian_types.hpp>
12#include <boost/date_time/posix_time/posix_time_types.hpp>
13#include <type_traits>
14
15namespace microfmt {
16namespace detail {
17
18template <typename Period> constexpr microfmt::string_view boost_duration_suffix() noexcept {
19 if constexpr (Period::num == 1 && Period::den == 1000000000) {
20 return "ns";
21 } else if constexpr (Period::num == 1 && Period::den == 1000000) {
22 return "us";
23 } else if constexpr (Period::num == 1 && Period::den == 1000) {
24 return "ms";
25 } else if constexpr (Period::num == 1 && Period::den == 1) {
26 return "s";
27 } else if constexpr (Period::num == 60 && Period::den == 1) {
28 return "min";
29 } else if constexpr (Period::num == 3600 && Period::den == 1) {
30 return "h";
31 } else {
32 return " [custom]";
33 }
34}
35
36inline void format_boost_date(const boost::gregorian::date &date, const sink &out) noexcept {
37 if (date.is_not_a_date()) {
38 out.write("not-a-date");
39 return;
40 }
41 if (date.is_pos_infinity()) {
42 out.write("+infinity");
43 return;
44 }
45 if (date.is_neg_infinity()) {
46 out.write("-infinity");
47 return;
48 }
49 detail::format_unsigned<detail::radix::decimal>(out, static_cast<uint64_t>(date.year()), false, 4);
50 out.put('-');
51 detail::format_unsigned<detail::radix::decimal>(out, static_cast<uint64_t>(date.month()), false, 2);
52 out.put('-');
53 detail::format_unsigned<detail::radix::decimal>(out, static_cast<uint64_t>(date.day()), false, 2);
54}
55
56inline void format_boost_time_duration(const boost::posix_time::time_duration &duration, const sink &out) noexcept {
57 if (duration.is_special()) {
58 if (duration.is_not_a_date_time()) {
59 out.write("not-a-date-time");
60 } else if (duration.is_pos_infinity()) {
61 out.write("+infinity");
62 } else {
63 out.write("-infinity");
64 }
65 return;
66 }
67
68 if (duration.is_negative()) {
69 out.put('-');
70 }
71 detail::format_unsigned<detail::radix::decimal>(
72 out, static_cast<uint64_t>(duration.hours() < 0 ? -duration.hours() : duration.hours()), false, 2);
73 out.put(':');
74 detail::format_unsigned<detail::radix::decimal>(
75 out, static_cast<uint64_t>(duration.minutes() < 0 ? -duration.minutes() : duration.minutes()), false, 2);
76 out.put(':');
77 detail::format_unsigned<detail::radix::decimal>(
78 out, static_cast<uint64_t>(duration.seconds() < 0 ? -duration.seconds() : duration.seconds()), false, 2);
79 const auto fractional = duration.fractional_seconds();
80 if (fractional != 0) {
81 out.put('.');
82 detail::format_unsigned<detail::radix::decimal>(
83 out, static_cast<uint64_t>(fractional < 0 ? -fractional : fractional), false,
84 static_cast<unsigned>(boost::posix_time::time_duration::num_fractional_digits()));
85 }
86}
87
88} // namespace detail
89
90template <typename Rep, typename Period> struct formatter<boost::chrono::duration<Rep, Period>> {
91 bool hide_suffix{false};
92
93 constexpr void parse(format_parse_context &ctx) noexcept {
94 for (const char character : ctx.spec()) {
95 if (character == 'c' || character == 'C') {
96 hide_suffix = true;
97 }
98 }
99 }
100
101 void format(const boost::chrono::duration<Rep, Period> &duration, const sink &out) const noexcept {
102 formatter<Rep> count_formatter;
103 format_parse_context count_context("");
104 count_formatter.parse(count_context);
105 count_formatter.format(duration.count(), out);
106 if (!hide_suffix) {
107 out.write(detail::boost_duration_suffix<Period>());
108 }
109 }
110};
111
112template <typename Clock, typename Duration> struct formatter<boost::chrono::time_point<Clock, Duration>> {
113 formatter<Duration> duration_formatter{};
114
115 constexpr void parse(format_parse_context &ctx) noexcept { duration_formatter.parse(ctx); }
116
117 void format(const boost::chrono::time_point<Clock, Duration> &time_point, const sink &out) const noexcept {
118 duration_formatter.format(time_point.time_since_epoch(), out);
119 out.write(" since epoch");
120 }
121};
122
123template <> struct formatter<boost::gregorian::date> {
124 constexpr void parse(format_parse_context &) noexcept {}
125
126 void format(const boost::gregorian::date &date, const sink &out) const noexcept {
127 detail::format_boost_date(date, out);
128 }
129};
130
131template <> struct formatter<boost::posix_time::time_duration> {
132 constexpr void parse(format_parse_context &) noexcept {}
133
134 void format(const boost::posix_time::time_duration &duration, const sink &out) const noexcept {
136 }
137};
138
139template <> struct formatter<boost::posix_time::ptime> {
140 constexpr void parse(format_parse_context &) noexcept {}
141
142 void format(const boost::posix_time::ptime &time, const sink &out) const noexcept {
143 if (time.is_not_a_date_time()) {
144 out.write("not-a-date-time");
145 return;
146 }
147 if (time.is_pos_infinity()) {
148 out.write("+infinity");
149 return;
150 }
151 if (time.is_neg_infinity()) {
152 out.write("-infinity");
153 return;
154 }
155 detail::format_boost_date(time.date(), out);
156 out.put('T');
157 detail::format_boost_time_duration(time.time_of_day(), out);
158 }
159};
160
161} // namespace microfmt
Definition microfmt.hpp:881
void format_boost_date(const boost::gregorian::date &date, const sink &out) noexcept
Definition boost_time.hpp:36
constexpr microfmt::string_view boost_duration_suffix() noexcept
Definition boost_time.hpp:18
void format_boost_time_duration(const boost::posix_time::time_duration &duration, const sink &out) noexcept
Definition boost_time.hpp:56
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
void format(const boost::chrono::duration< Rep, Period > &duration, const sink &out) const noexcept
Definition boost_time.hpp:101
constexpr void parse(format_parse_context &ctx) noexcept
Definition boost_time.hpp:93
constexpr void parse(format_parse_context &ctx) noexcept
Definition boost_time.hpp:115
void format(const boost::chrono::time_point< Clock, Duration > &time_point, const sink &out) const noexcept
Definition boost_time.hpp:117
void format(const boost::gregorian::date &date, const sink &out) const noexcept
Definition boost_time.hpp:126
constexpr void parse(format_parse_context &) noexcept
Definition boost_time.hpp:124
constexpr void parse(format_parse_context &) noexcept
Definition boost_time.hpp:140
void format(const boost::posix_time::ptime &time, const sink &out) const noexcept
Definition boost_time.hpp:142
constexpr void parse(format_parse_context &) noexcept
Definition boost_time.hpp:132
void format(const boost::posix_time::time_duration &duration, const sink &out) const noexcept
Definition boost_time.hpp:134
Definition microfmt.hpp:985