BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlt_formatdoc.h
Go to the documentation of this file.
1/// @file bdlt_formatdoc.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlt_formatdoc.h -*-C++-*-
8#ifndef INCLUDED_BDLT_FORMATDOC
9#define INCLUDED_BDLT_FORMATDOC
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlt_formatdoc bdlt_formatdoc
15/// @brief Provide documentation for `bsl::format` of bdlt value types
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlt
19/// @{
20/// @addtogroup bdlt_formatdoc
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlt_formatdoc-purpose"> Purpose</a>
25/// * <a href="#bdlt_formatdoc-description"> Description </a>
26/// * <a href="#bdlt_formatdoc-usage"> Usage </a>
27///
28/// # Purpose {#bdlt_formatdoc-purpose}
29/// Provide documentation for `bsl::format` of bdlt value types
30///
31/// # Description {#bdlt_formatdoc-description}
32/// This component provides documentation and a usage example
33/// demonstrating the behavior and features of `bsl::format` as applied to bdlt
34/// value types.
35///
36///@SEE ALSO: bdlt_dateformatter, bdlt_datetzformatter, bdlt_timeformatter,
37/// bdlt_timetzformatter, bdlt_datetimeformatter, bdlt_datetimetzformatter
38///
39/// `bsl::format` is a powerful formatting function that can be used to format,
40/// among other things, `bdlt` value types. The formatting of types is
41/// controlled by a set of formatting options that are specified in the format
42/// string passed to `bsl::format` in a way very similar to how the format
43/// string in `printf` formats types being printed. While `printf` can only
44/// format a few hard-coded types, `bsl::format` can be extended to format more
45/// sophisticated types, and all `bdlt` value types are supported with such
46/// extensions.
47///
48/// The format string passed to `bsl::format` can contain any number of `%`
49/// sequences, which are replaced by the formatted value of the corresponding
50/// argument, or part of the corresponding argument. Each type has a specific,
51/// limited set of `%`-sequences that can be used with it, and using any other
52/// `%`-sequence is an error. The formatting options for `bdlt` value types
53/// are described both in this component and in the component documentation of
54/// each `bdlt` value type.
55///
56/// The following is a list of `%`-sequences supported for `bdlt` value types,
57/// though not all the sequences are supported for all the types. Many of the
58/// sequences are copied from `std::format`s support for
59/// `std::chrono::duration`, see
60/// https://en.cppreference.com/w/cpp/chrono/duration.html, but some other ones
61/// are specific to `bdlt` value types.
62///
63/// Just like for all other `bsl::format` errors, errors will be detected at
64/// compile time in C++20 and later, but in C++17 and earlier, errors will
65/// result in an exception being thrown at run time.
66///
67/// Literal `%` sequences that just output one fixed character are:
68/// * Literal: `"%%"` - outputs (`"%"`)
69/// * Literal: `"%n"` - outputs newline (`"\n"`)
70/// * Literal: `"%t"` - outputs tab (`"\t"`)
71///
72/// All `%` sequences supported for `bdlt` value types are:
73/// * Date alone: `"%D"` same as `"{:%d%h%Y}"`
74/// * Date alone: `"%F"` Iso8601, like `"{:%Y-%m-%d}"`
75/// * Time alone: `"%T"`, same as `"{:%H:%M:%S}"`, 6 digit fraction
76/// * Time zone: `"%z"`, 2 digit hour and 2-digit minute offset from UTC, with
77/// or without a colon separating hours and minutes
78/// * Year: `"%Y"` (4-digit), `"%y"` (2-digit)
79/// * Century: `"%C"` (2-digit)
80/// * Numeric month: `"%m"` (2-digit)
81/// * Abbreviation of month: (always 3-letter upper case): `"%b"` or `"%h"`
82/// * Day of month: (always 2-digit) `"%d"` (`0`-padded), `"%e"` (space-padded)
83///
84/// * Abbreviated day of week: `"%a"` (3 letter upper case)
85/// * Day of week: `"%u"` (numeric 1-7, Monday is 1)
86/// * Day of week: `"%w"` (numeric 0-6, Sunday is 0)
87/// * Day of year: `"%j"` (numeric 3-digit)
88/// * Hour: `"%H"` (2 digit) `00` - `24`
89/// * Hour: `"%I"` (2 digit) `01` - `12`
90/// * AM/PM: `"%p"` - `AM` or `PM`
91/// * Minute: `"%M"` (2 digits) `00` - `59`
92/// * Second: `"%S"` (2 digits `00` - `59` + `.` + fraction)
93///
94/// * Composite: `"{}"` formats the value as if streamed by `<<`, default 6
95/// digit precision for seconds, no `:` between hours and minutes of any
96/// time zone
97/// * Composite: `"%i"` for bdlt value types formats the entire value like
98/// Iso8601, were precision defaults to 3 digit and there's a `:` between
99/// hours and minutes of any time zone.
100///
101/// It is an error to specify a `%`-sequence that does not apply to the type
102/// being formatted, or a sub-type of it -- for example, all sequences that
103/// apply to `Date` or `Time` can be used on a `Datetime` object.
104///
105/// `bsl::format` strings of bdlt value types take the form of either `"{}"` or
106/// `"{:[padding][precision][bdlt-modifiers]["%"-sequences]}"` where all fields
107/// surrounded by `"[]"`s are optional. While in `printf` the modifiers of a
108/// `%`-sequence occur between the `%` and the type specifier, in
109/// `bsl::format` the modifiers occur between the first `:` and the first `%`
110/// (if any).
111///
112/// * The `padding` takes the form of
113/// `<pad character><alignment command><width>` where
114/// - `<pad character>` is the character to pad with, which defaults to space
115/// if omitted, and must be a single character
116/// - `<alignment command>` is one of: `<` for left, `>` for right, and `^`
117/// for centered, and
118/// - `<width>` is the minimum total width of the padded value output
119/// * The `precision` is indicated by a `.` followed by an integral number of
120/// digits.
121/// * The `bdlt`-modifiers are specific to `bdlt` value types. One affects the
122/// output of seconds, and three affect the output of time zones:
123/// - `,` decimal between integral seconds and fraction is a comma instead
124/// of a period
125/// - `:` separate hours and minutes in time zone with `:`
126/// - `_` suppress `:` between hours and minutes in time zone
127/// - `Z` if time zone offset is 0, display it as `Z`
128/// Characters after the first `%` that are not part of a valid `%`-sequence
129/// are copied to output without modification. The modifiers must come in the
130/// order `"<padding><precision><bdlt-specific modifiers>"`. The bdlt-specific
131/// modifiers must come last, but among themselves, may occur in any order.
132///
133/// ## Usage {#bdlt_formatdoc-usage}
134///
135///
136/// First, include the files necessary to declare the `bdlt` value types that we
137/// will use and their formatters:
138/// @code
139/// #include <bdlt_date.h>
140/// #include <bdlt_dateformatter.h>
141/// #include <bdlt_datetimetz.h>
142/// #include <bdlt_datetimetzformatter.h>
143/// #include <bdlt_timetz.h>
144/// #include <bdlt_timetzformatter.h>
145/// @endcode
146/// Next, create a form of assertion macro that will compare a literal string to
147/// the result of an expression and output the value of the expression if they
148/// don't match (continuations elided in .h to suppress compiler errors):
149/// @code
150/// #undef U_EQ
151/// #define U_EQ(expectedString, rhsExpr) do {
152/// const bsl::string& s = rhsExpr;
153/// if (expectedString != s) {
154/// cout << "Error:(" << __LINE__ << "): " <<
155/// "\"" expectedString "\"" <<
156/// " != " << "(" #rhsExpr ": \"" << s << "\")" << endl;
157/// assert(0);
158/// }
159/// } while (false)
160/// @endcode
161/// Declare a few variables of bdlt value types:
162/// @code
163/// const bdlt::Time TIME(14, 32, 17, 123, 456);
164/// const bdlt::TimeTz TIME_TZ(TIME, 300);
165/// const bdlt::Date DATE(1776, 7, 4);
166/// const bdlt::Datetime DATETIME(DATE, TIME);
167/// const bdlt::DatetimeTz DATETIME_TZ(DATETIME, 0);
168///
169/// bsl::ostringstream oss;
170/// @endcode
171/// The simplest way to format a bdlt type using `bsl::format` is to use the
172/// "{}" format string. In this case, `bsl::format` will produce the same
173/// output as streaming that value into a `bsl::ostream`. If more control is
174/// required, we can use `%`-sequences to select which parts of the value are
175/// formatted, in which order, and to add any text to separate them.
176///
177/// A `Time` can also be formatted with `"%T"`:
178/// @code
179/// oss.str(""); oss << TIME;
180/// U_EQ("14:32:17.123456", oss.str());
181/// U_EQ("14:32:17.123456", bsl::format("{}", TIME));
182/// U_EQ("14:32:17.123456", bsl::format("{:%T}", TIME));
183/// U_EQ("14:32:17.123456 -- boo!", bsl::format("{:%T -- boo!}", TIME));
184/// @endcode
185/// A `Date` can be formatted with `"%D"`:
186/// @code
187/// oss.str(""); oss << DATE;
188/// U_EQ("04JUL1776", oss.str());
189/// U_EQ("04JUL1776", bsl::format("{}", DATE));
190/// U_EQ("04JUL1776", bsl::format("{:%D}", DATE));
191/// @endcode
192/// The `format` function can print multiple variables in a single call:
193/// @code
194/// U_EQ("04JUL1776 .. 14:32:17.123456", bsl::format("{} .. {}", DATE, TIME));
195/// @endcode
196/// In bdlt formatting, any `%`-sequence that works on a type also works on
197/// other types that contain that type, and time zones can be formatted as
198/// `"%z"`.
199/// @code
200/// oss.str(""); oss << TIME_TZ;
201/// U_EQ("14:32:17.123456+0500", oss.str());
202/// U_EQ("14:32:17.123456+0500", bsl::format("{}", TIME_TZ));
203/// U_EQ("14:32:17.123456+0500", bsl::format("{:%T%z}", TIME_TZ));
204///
205/// oss.str(""); oss << DATETIME;
206/// U_EQ("04JUL1776_14:32:17.123456", oss.str());
207/// U_EQ("04JUL1776_14:32:17.123456", bsl::format("{}", DATETIME));
208/// U_EQ("04JUL1776_14:32:17.123456", bsl::format("{:%D_%T}", DATETIME));
209///
210/// oss.str(""); oss << DATETIME_TZ;
211/// U_EQ("04JUL1776_14:32:17.123456+0000", oss.str());
212/// U_EQ("04JUL1776_14:32:17.123456+0000", bsl::format("{}", DATETIME_TZ));
213/// U_EQ("04JUL1776_14:32:17.123456+0000",
214/// bsl::format("{:%D_%T%z}", DATETIME_TZ));
215/// @endcode
216/// `%`-sequences can appear any number of times:
217/// @code
218/// U_EQ("04JUL1776 == 04JUL1776 == 04JUL1776!!!",
219/// bsl::format("{:%D == %D == %D!!!}", DATETIME_TZ));
220/// @endcode
221/// After the first `:` and before the first `%`, if any, one can indicate
222/// padding with "<pad char><alignment char><width>" where:
223/// * <pad char> -- the character to pad with, (space if omitted)
224/// * <alignment char> -- `<` for left, `>` for right, `^` for centered
225/// * <width> -- minimum total width of the value output
226///
227/// @code
228/// U_EQ("14:32:17.123456 ", bsl::format("{:<25%T}", TIME));
229/// U_EQ("*****14:32:17.123456*****", bsl::format("{:*^25%T}", TIME));
230/// U_EQ("++++++++++14:32:17.123456", bsl::format("{:+>25}", TIME));
231/// @endcode
232/// After the padding specification (if any) and before the first `%` (if any),
233/// one can indicate the `precision`, the number of digits of fractional
234/// seconds. This is specified as a period followed by a non-negative integral
235/// number of digits to occur after the decimal. If the precision is 0, no
236/// decimal will be shown:
237/// @code
238/// U_EQ("14:32:17.12", bsl::format("{:.2}", TIME));
239/// U_EQ("14:32:17.12", bsl::format("{:.2%T}", TIME));
240/// U_EQ("14:32:17", bsl::format("{:.0}", TIME));
241/// U_EQ("14:32:17.123456000000000", bsl::format("{:.15}", TIME));
242/// @endcode
243/// After the padding and/or precision specifiers (if any), when formatting
244/// `bdlt` types, one can provide modifiers that change the behavior of the
245/// correlating `%`-sequences. Currently, there is one modifier that affects
246/// the formatting of fractional seconds and three modifiers that affect time
247/// zone formatting:
248/// * `,` the decimal in `seconds` is to be a comma rather than a period
249/// * `:` always separate time zone hours and minutes by colon
250/// * `_` never separate time zone hours and minutes by colon
251/// * `Z` if the time zone offset is zero, print it as `Z`, otherwise, the `Z`
252/// modifier is ignored
253///
254/// @code
255/// U_EQ("14:32:17.12", bsl::format("{:.2%T}", TIME_TZ));
256/// U_EQ("14:32:17,12", bsl::format("{:.2,%T}", TIME_TZ)); // comma
257/// U_EQ("14:32:17+05:00", bsl::format("{:.0:}", TIME_TZ)); // colon
258/// U_EQ("14:32:17+0500", bsl::format("{:.0}", TIME_TZ)); // default tz
259/// U_EQ("14:32:17+0500", bsl::format("{:.0Z}", TIME_TZ)); // `Z` ignored
260///
261/// U_EQ("14:32:17+00:00", bsl::format("{:.0:%T%z}", DATETIME_TZ)); // no `Z`
262/// U_EQ("14:32:17Z", bsl::format("{:.0:Z%T%z}", DATETIME_TZ)); // `Z`
263/// @endcode
264/// Errors in the format string such as:
265/// * using a `%`-sequence that is not supported for that type
266/// * Specifying padding, precision, and bdlt-modifiers in the wrong order
267/// (among themselves, bdlt-modifiers may appear in any order)
268/// * Specifying bdlt-modifiers that are inapplicable to the type
269/// * any characters between the first `:` and the first `%`-sequence that are
270/// not part of a valid padding specification, precision, or bdlt-modifier
271/// will cause a compilation error in C++20 or later, or cause a
272/// `bsl::format_error` exception to be thrown at runtime in C++17 or earlier.
273///
274/// Padding width and precision can be passed through the argument list at run
275/// time:
276/// @code
277/// U_EQ("+++14:32:17,12+++", bsl::format("{:+^{}.{},}", TIME, 17, 2));
278/// @endcode
279/// `"%i"` - format the whole value according to the same format as
280/// `bdlt::Iso8601::generate`. Iso8601 formatting differs from formatting the
281/// value with the "{}" format string in several ways:
282/// * precision defaults to 3 rather than 6
283/// * time zones default to having a `:` between hours and minutes, rather than
284/// no separator
285/// * `Date`s are done in the format "YYYY-MM-DD" rather than "DDMMMYYYY", so
286/// that when sorted, they will sort chronologically
287/// * the date and time in a `Datetime` are separated by `T` rather than `_`
288///
289/// `"%i"`-sequences are supported for all bdlt value types:
290/// @code
291/// U_EQ("14:32:17.123", bsl::format("{:%i}", TIME));
292/// U_EQ("14:32:17.123+05:00", bsl::format("{:%i}", TIME_TZ));
293/// U_EQ("1776-07-04", bsl::format("{:%i}", DATE));
294/// U_EQ("1776-07-04T14:32:17.123+00:00", bsl::format("{:%i}", DATETIME_TZ));
295/// @endcode
296/// The `_` bdlt-modifier can be used to suppress the colon in the time zone:
297/// @code
298/// U_EQ("14:32:17.123+0500", bsl::format("{:_%i}", TIME_TZ));
299/// @endcode
300/// `bsl::format` does not support showing names or abbreviations of time zones,
301/// they are always listed as numerical hours & minutes.
302///
303/// Using various `%`-sequences, one can arrange different pieces of the value
304/// in any desired order. For example, it is possible to replicate the `"%i"`
305/// format using other sequences:
306/// @code
307/// U_EQ("1776-07-04T14:32:17.123+00:00", bsl::format("{:%i}", DATETIME_TZ));
308/// U_EQ("1776-07-04T14:32:17.123+00:00",
309/// bsl::format("{:.3:%FT%T%z}", DATETIME_TZ));
310/// U_EQ("1776-07-04T14:32:17.123+00:00",
311/// bsl::format("{:.3:%Y-%m-%dT%H:%M:%S%z}", DATETIME_TZ));
312/// @endcode
313/// Other `%`-sequences can be used to arrange the value in other ways, or to
314/// achieve specific output formats. For example:
315/// @code
316/// U_EQ("THU, JUL 04, 02:32:17 PM, 1776",
317/// bsl::format("{:.0%a, %b %d, %I:%M:%S %p, %Y}", DATETIME));
318///
319/// U_EQ("JUL 4 1776", bsl::format("{:%h %e %C%y}", DATE));
320///
321/// const bdlt::Date SUNDAY(1776, 6, 30);
322///
323/// U_EQ("Sunday %a: SUN, Sunday %u: 7, Sunday %w: 0", bsl::format(
324/// "Sunday %a: {:%a, Sunday %%u: %u, Sunday %%w: %w}", SUNDAY));
325///
326/// U_EQ("Day of year Sunday: 182, Thursday: 186", bsl::format(
327/// "Day of year Sunday: {:%j}, Thursday: {:%j}", SUNDAY, DATE));
328/// @endcode
329/// @}
330/** @} */
331/** @} */
332
333/** @addtogroup bdl
334 * @{
335 */
336/** @addtogroup bdlt
337 * @{
338 */
339/** @addtogroup bdlt_formatdoc
340 * @{
341 */
342
343#include <bdlscm_version.h>
344
345#endif
346
347// ----------------------------------------------------------------------------
348// Copyright 2026 Bloomberg Finance L.P.
349//
350// Licensed under the Apache License, Version 2.0 (the "License");
351// you may not use this file except in compliance with the License.
352// You may obtain a copy of the License at
353//
354// http://www.apache.org/licenses/LICENSE-2.0
355//
356// Unless required by applicable law or agreed to in writing, software
357// distributed under the License is distributed on an "AS IS" BASIS,
358// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
359// See the License for the specific language governing permissions and
360// limitations under the License.
361// ----------------------------- END-OF-FILE ----------------------------------
362
363/** @} */
364/** @} */
365/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238